gpt4 book ai didi

python - 为什么 sys.excepthook 在包装时表现不同?

转载 作者:太空狗 更新时间:2023-10-30 01:04:50 24 4
gpt4 key购买 nike

Qt 静静地捕捉 Python 回调中的异常并使用错误代码退出程序。这可以用一个简短的例子来证明:

import sys
from PyQt5 import QtWidgets

# _excepthook = sys.excepthook
# def exception_hook(exctype, value, traceback):
# _excepthook(exctype, value, traceback)
# sys.excepthook = exception_hook

class Test(QtWidgets.QPushButton):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.setText("hello")
self.clicked.connect(self.buttonClicked)

def buttonClicked(self):
print("clicked")
raise Exception("wow")

app = QtWidgets.QApplication(sys.argv)
t = Test()
t.show()
app.exec_()

点击按钮我们得到

clicked

Process finished with exit code 1

This answer (我从中修改了示例)展示了如何安装自定义异常 Hook 。因此,让我们取消注释上面示例中的代码行。现在它会打印回溯并且不会在我们每次单击按钮时退出程序。

自定义函数只是旧函数的薄包装。为什么这会在引发异常时导致不同的行为?

最佳答案

在 PyQt4 和 PyQt5 的旧版本(5.4 或更早版本)中,行为是在您描述的任何情况下都不会退出应用程序。这在 PyQt 5.5+ 中已更改(导致应用程序退出),但前提是没有为 sys.excepthook 明确指定的异常处理程序。这在 documentation 中有所提及。但也有关于 mailing list 的更多详细信息.

文档中的相关部分:

There are a number of situations where Python code is executed from C++. Python reimplementations of C++ virtual methods is probably the most common example. In previous versions, if the Python code raised an exception then PyQt would call Python’s PyErr_Print() function which would then call sys.excepthook(). The default exception hook would then display the exception and any traceback to stderr. There are number of disadvantages to this behaviour:

  • the application does not terminate, meaning the behaviour is different to when exceptions are raised in other situations
  • the output written to stderr may not be seen by the developer or user (particularly if it is a GUI application) thereby hiding the fact that the application is trying to report a potential bug.

This behaviour was deprecated in PyQt v5.4. In PyQt v5.5 an unhandled Python exception will result in a call to Qt’s qFatal() function. By default this will call abort() and the application will terminate. Note that an application installed exception hook will still take precedence.

邮件列表线程的相关部分:

I have just discovered the change to PyQt 5.5 in which unhandled exceptions result in a call to qFatal(). Perhaps I am missing something important, but I am a confused about why this behavior was chosen. The documentation states that the problem with the old behavior is that "the application does not terminate, meaning the behaviour is different to when exceptions are raised in other situations". I have two concerns about this reasoning:

因为你不能在当前运行时干净地退出 Python C++代码。

  1. Unhandled exceptions in Python do not cause the program to terminate; they only cause sys.excepthook to be invoked.

与 PyQt 相同,如果你设置一个。

也许还值得指出的是,最初的问题是由 pyqtgraph 的创建者在 pyqt 邮件列表中提出的,并且 riverbank computing 的工作人员表示这种新行为不会消失。

如果想看源码,相关代码位于pyqt5/qpy/QtCore/qpycore_public_api.cpp(PyQt5的fork版本为here)

关于python - 为什么 sys.excepthook 在包装时表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49065371/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com