【问题标题】:Catching exceptions raised in QApplication捕获 QApplication 中引发的异常
【发布时间】:2019-09-13 02:49:51
【问题描述】:

我正在尝试使用 PyQt5 编写一个在系统托盘中运行的应用程序。 代码有时会引发异常,我需要能够捕获它们。

我希望当应用程序中发生异常时,主事件循环会退出,所以像这样捕获它应该可以工作:

try:
    application.exec()
except:
    do_stuff()

在下面的例子中,当我按下“Raise”按钮时,我只看到了回溯,但我从来没有看到 error catched! 打印出来。

from PyQt5 import QtWidgets, QtGui, QtCore

class ErrorApp():
    def __init__(self):
        # Init QApplication, QWidet and QMenu
        self.app = QtWidgets.QApplication([])
        self.widget = QtWidgets.QWidget()
        self.menu = QtWidgets.QMenu("menu", self.widget)

        # Add items to menu
        self.menu_action_raise = self.menu.addAction("Raise")
        self.menu_action_raise.triggered.connect(self.raise_error)

        self.menu_action_exit = self.menu.addAction("Exit")
        self.menu_action_exit.triggered.connect(self.app.exit)

        # Create the tray app
        self.tray = QtWidgets.QSystemTrayIcon(QtGui.QIcon("logo.png"), self.widget)
        self.tray.setContextMenu(self.menu)

        # Show app
        self.tray.show()

    def raise_error(self):
        assert False

e = ErrorApp()

try:
    e.app.exec()

except:
    print("error catched!")

有 2 个类似的问题,但那里的答案没有做我需要做的事情:

Grab any exception in PyQt: OP 想要监控异常,偶数循环没有退出 Preventing PyQt to silence exceptions occurring in slots:装饰师的回答根本行不通;将sys.exit(1) 添加到sys.excepthook 只会关闭整个程序,而不打印error catched!

【问题讨论】:

    标签: python exception pyqt pyqt5


    【解决方案1】:

    您必须使用异常,并且如果您希望事件循环结束,那么您必须调用quit()(或exit())方法。

    import sys
    import traceback
    from PyQt5 import QtWidgets, QtGui, QtCore
    
    
    class ErrorApp:
        # ...
    
        def raise_error(self):
            assert False
    
    
    def excepthook(exc_type, exc_value, exc_tb):
        tb = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
        print("error catched!:")
        print("error message:\n", tb)
        QtWidgets.QApplication.quit()
        # or QtWidgets.QApplication.exit(0)
    
    
    sys.excepthook = excepthook
    e = ErrorApp()
    ret = e.app.exec_()
    print("event loop exited")
    sys.exit(ret)
    

    输出:

    error catched!:
    error message:
     Traceback (most recent call last):
      File "main.py", line 28, in raise_error
        assert False
    AssertionError
    
    event loop exited
    

    【讨论】:

    • 哦,我明白了——我必须在异常钩子中处理它,而不是我的尝试。谢谢:)
    • 普通的sys.__excepthook__(exc_type, exc_value, exc_tb)函数应该在exepthook函数结束时调用吗?
    • exitQCoreApplication 的静态方法,quitQCoreApplication 的“静态槽”(不知道有什么区别)。在QApplication 的“包括继承的所有成员列表”中,它包括exit(显然链接到QCoreApplication 文档页面),但不包括quit。然而,两者似乎都按照您的代码工作。我们是否只是假设这些static 方法/槽只是“落入”适当的超类?
    • @mikerodent quit()确实出现在QApplication成员列表中,quit()在primaryScreenChanged之后的第一列,看来顺序是先放properties、signals、slots再放其他方法。注意:slot 是在 QMetaObject 中注册的函数。
    猜你喜欢
    • 1970-01-01
    • 2012-06-05
    • 2014-10-07
    • 2013-12-14
    • 2014-03-07
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多