查看以下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_()
我有很多问题。我不知道他们是否都是相关的(我猜是这样),所以请原谅我,如果他们不是。
当我从终端运行上面的代码时,一切都很好。该程序运行,如果我点击按钮它会打印回溯并死掉。如果我在IDE中运行它(我测试了Spyder和PyCharm),则不会显示回溯。知道为什么吗?在SO,here和here上的其他帖子中也提出了同样的问题。请不要将此标记为其中任何一个的副本;请继续阅读。
通过添加注释行,可以再次正确显示回溯。但是,他们也有令人讨厌的副作用,应用程序不再终止未处理的异常!我不知道为什么会发生这种情况,因为AFAIK excepthook
仅打印回溯,它无法阻止程序退出。在被召唤的那一刻,救援已经太晚了。
另外,我不明白Qt是如何在这里发挥作用的,因为插槽中没有引发的异常仍然会像我期望的那样使应用程序崩溃。无论我是否更改excepthook
,PyQt似乎也不会覆盖它(至少print
似乎建议如此)。
仅供参考,我使用Python 3.5和PyQt 5.6,我知道PyQt 5.5中引入的异常处理的变化。如果这些确实是上述行为的原因,我会很高兴听到一些更详细的解释。
答案 0 :(得分:2)
当Qt插槽内发生异常时,它是调用Python代码的C ++。由于Qt / C ++对Python异常一无所知,因此您只有两种可能性:
Python仍然没有终止的原因可能是因为它不能,因为它在一些C ++代码中。您的IDE没有显示堆栈的原因可能是因为它没有正确处理abort()
- 我建议为此针对IDE打开一个错误。