PyQt5中未处理的异常

pol*_*wel 5 python ide qt unhandled-exception pyqt5

看看下面的MWE。

import sys

from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.button = QPushButton('Bham!')
        self.setCentralWidget(self.button)
        self.button.clicked.connect(self.btnClicked)

    def btnClicked(self):
        print(sys.excepthook)
        raise Exception


#import traceback
#sys.excepthook = traceback.print_exception

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    app.exec_() 
Run Code Online (Sandbox Code Playgroud)

我有很多问题。我不知道它们是否都相关(我想是的),如果它们不相关,请原谅我。

  1. 当我从终端运行以上代码时,一切都很好。该程序运行,如果我单击按钮,它将打印回溯并消失。如果我在IDE(我测试过Spyder和PyCharm)中运行它,则不会显示回溯。知道为什么吗?从本质上讲,在此处此处的其他帖子中也提出了相同的问题。请不要将此标记为其中任何一个的重复;请继续阅读。

  2. 通过添加注释行,可以再次正确显示回溯。但是,它们还具有讨厌的副作用,即该应用程序不会再因未处理的异常而终止!我不知道为什么会这样,因为AFAIK excepthook打印回溯,它不能阻止程序退出。目前,救援已经为时已晚。

  3. 另外,我不了解Qt在这里如何发挥作用,因为未在插槽内引发的异常仍会像我期望的那样使应用程序崩溃。无论我是否进行更改excepthook,PyQt似乎都不会覆盖它(至少print似乎暗示了这一点)。

仅供参考,我正在将Python 3.5与PyQt 5.6配合使用,并且我知道PyQt 5.5中引入的异常处理方面的变化。如果确实是上述行为的原因,我很高兴听到一些更详细的解释。

The*_*ler 4

当 Qt 插槽内发生异常时,C++ 会调用您的 Python 代码。由于 Qt/C++ 对 Python 异常一无所知,因此您只有两种可能性:

  • 打印异常并向 C++ 返回一些默认值(如 0、“”或 NULL),这可能会产生意想不到的副作用。这就是 PyQt < 5.5 所做的。
  • 打印异常,然后调用qFatal()abort(),导致应用程序立即退出 C++ 内部。这就是 PyQt >= 5.5 所做的事情,除非您设置了自定义 excepthook 。

Python 仍然没有终止的原因可能是因为它不能终止,因为它位于某些 C++ 代码中。您的 IDE 未显示堆栈的原因可能是因为它没有正确处理abort()- 我建议为此针对 IDE 打开一个错误。