防止PyQt使插槽中发生的异常静音

Ste*_*ini 23 python pyqt

据我所见,如果在PyQt下的插槽中发生异常,则会将异常打印到屏幕,但不会冒泡.这会在我的测试策略中产生问题,因为如果插槽中发生异常,我将看不到测试失败.

这是一个例子:

import sys
from PyQt4 import QtGui, QtCore

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

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

app=QtGui.QApplication(sys.argv)
t=Test()
t.show()
try:
    app.exec_()
except:
    print "exiting"
Run Code Online (Sandbox Code Playgroud)

请注意异常永远不会退出程序.

有办法解决这个问题吗?

jlu*_*jan 19

可以创建一个包装PyQt的新信号/槽装饰器的装饰器,并为所有插槽提供异常处理.也可以覆盖QApplication :: notify来捕获未捕获的C++异常.

import sys
import traceback
import types
from functools import wraps
from PyQt4 import QtGui, QtCore

def MyPyQtSlot(*args):
    if len(args) == 0 or isinstance(args[0], types.FunctionType):
        args = []
    @QtCore.pyqtSlot(*args)
    def slotdecorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                func(*args)
            except:
                print "Uncaught Exception in slot"
                traceback.print_exc()
        return wrapper

    return slotdecorator

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

    @MyPyQtSlot("bool")
    def buttonClicked(self, checked):
        print "clicked"
        raise Exception("wow")

class MyApp(QtGui.QApplication):
    def notify(self, obj, event):
        isex = False
        try:
            return QtGui.QApplication.notify(self, obj, event)
        except Exception:
            isex = True
            print "Unexpected Error"
            print traceback.format_exception(*sys.exc_info())
            return False
        finally:
            if isex:
                self.quit()

app = MyApp(sys.argv)

t=Test()
t.show()
try:
    app.exec_()
except:
    print "exiting"
Run Code Online (Sandbox Code Playgroud)


auk*_*ost 12

您可以使用非零返回代码退出应用程序以指示发生了异常.
您可以通过安装全局异常挂钩来捕获所有异常.我在下面添加了一个示例,但您可能希望根据需要进行调整.

import sys
from PyQt4 import QtGui, QtCore

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

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

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

app=QtGui.QApplication(sys.argv)
t=Test()
t.show()
try:
    app.exec_()
except:
    print "exiting"
Run Code Online (Sandbox Code Playgroud)

  • **这是明智的解决方案。** 演示如何保留和遵循标准的 `sys.excepthook` 实现特别有用。 (2认同)