Exception handling PyQt事件处理程序snarf异常

Exception handling PyQt事件处理程序snarf异常,exception-handling,pyqt,pyqt4,Exception Handling,Pyqt,Pyqt4,下面是说明问题的代码: from PyQt4 import QtGui app = QtGui.QApplication([]) dialog = QtGui.QDialog() button = QtGui.QPushButton('I crash') layout = QtGui.QHBoxLayout() layout.addWidget(button) dialog.setLayout(layout) def crash(): raise Exception('Crash!') butt

下面是说明问题的代码:

from PyQt4 import QtGui
app = QtGui.QApplication([])
dialog = QtGui.QDialog()
button = QtGui.QPushButton('I crash')
layout = QtGui.QHBoxLayout()
layout.addWidget(button)
dialog.setLayout(layout)
def crash(): raise Exception('Crash!')
button.clicked.connect(crash)
button.click()
print 'I should not happen'
当我运行它时,PyQt4为我处理错误。我的控制台显示带有“崩溃”的堆栈跟踪等等,我看到‘我不应该发生’

这是没有用的,因为我已经收到了一个包含许多处理程序的大型应用程序,我需要将它们的所有错误强制到我的脸上(以及我的自动化测试中)。每次我运行时,错误都会从我的网络中逃逸出来,它们需要大量无用的尝试:除了块,在每个处理程序中,只是为了捕捉它们

换句话说,我希望好代码非常好,坏代码非常坏。没有粉饰

如果已经有人问过,我会道歉,但当我在网上搜索时,我自然会有成千上万的新手问一些基本的错误处理问题(或者,更糟糕的是,我会有新手问如何关闭他们任性的异常!)


如何覆盖PyQt4的默认错误处理,以便自己传播或记录错误?请不要回答Sy.例外,也就是说,它捕获了PyQT4没有捕获的错误。

< P>我认为答案不是“代码”> PyQt < /COD>,而是设计让信号/时隙工作的固有后果(记住信号/时隙通信也通过C++层)。 这很难看,但是否有一点和结束运行围绕你的问题

from PyQt4 import QtGui
import time
app = QtGui.QApplication([])

class exception_munger(object):
    def __init__(self):
        self.flag = True
        self.txt = ''
        self.type = None

    def indicate_fail(self,etype=None, txt=None):
        self.flag = False
        if txt is not None:
            self.txt = txt
        self.type = etype
    def reset(self):

        tmp_txt = self.txt
        tmp_type = self.type
        tmp_flag = self.flag
        self.flag = True
        self.txt = ''
        self.type = None
        return tmp_flag, tmp_type, tmp_txt

class e_manager():
    def __init__(self):
        self.old_hook = None

    def __enter__(self):
        em = exception_munger()
        def my_hook(type, value, tback):
            em.indicate_fail(type, value)
            sys.__excepthook__(type, value, tback) 
        self.old_hook = sys.excepthook
        sys.excepthook = my_hook
        self.em = em
        return self

    def __exit__(self,*args,**kwargs):
        sys.excepthook = self.old_hook

def mang_fac():
    return e_manager()

def assert_dec(original_fun):

    def new_fun(*args,**kwargs):
        with mang_fac() as mf:
            res = original_fun(*args, **kwargs)
            flag, etype, txt = mf.em.reset()
            if not flag:
                raise etype(txt)
            return res
    return new_fun


@assert_dec
def my_test_fun():
    dialog = QtGui.QDialog()
    button = QtGui.QPushButton('I crash')
    layout = QtGui.QHBoxLayout()
    layout.addWidget(button)
    dialog.setLayout(layout)
    def crash(): 
        time.sleep(1)
        raise Exception('Crash!')
    button.clicked.connect(crash)


    button.click()

my_test_fun()
print 'should not happen'
这不会打印“不应该发生”,并为您的自动测试提供一些信息(使用正确的异常类型)

[11]中的
:回溯(最近一次调用):
文件“/tmp/ipython2-3426rwB.py”,第68行,在崩溃中
例外:崩溃!
---------------------------------------------------------------------------
异常回溯(最后一次最近调用)
在()
---->1个execfile(r'/tmp/ipython2-3426rwB.py')#PYTHON-MODE
/tmp/ipython2-3426rwB.py英寸()
/tmp/ipython2-3426rwB.py在新_fun(*args,**kwargs)
例外:崩溃!
在[12]中:

堆栈跟踪被顶起,但您仍然可以读取打印出来的第一个堆栈跟踪。

这不是答案,您这个愚蠢的网站。不要强迫我们去适应一个理想化线程模板的先入为主的概念

解决方法是使用my test framework setUp()挂接异常处理程序:

def setUp(self):
    self.no_exceptions = True

    def testExceptionHook(type, value, tback):
        self.no_exceptions = False
        sys.__excepthook__(type, value, tback)

    sys.excepthook = testExceptionHook
如果说“self.no_exceptions=False”,我宁愿简单地说self.fail(“”)。然而,因为Python的单元测试库坚持抛出异常只是为了注册测试失败,而且因为PyQt坚持捕捉所有异常,所以我们出现了死锁

为了适应unittest.TestCase对理想化测试用例的愚蠢先入为主的概念,我必须设置一个变量,然后在拆卸中检测它:

def tearDown(self):
    self.assertTrue(self.no_exceptions)
这仍然不理想,但至少会迫使我花更多的时间关注错误,而不是花时间在技术网站上抱怨错误


根本问题:如何关闭PyQt的神奇错误处理程序仍然没有回答…

我想你的问题是异常发生在
PyQt
事件循环运行的地方(我认为这是另一个线程),所以你真的在问如何在线程之间移动异常。sry no-我发布的代码已经完成。没有MainLoop事件调度器;我只是直接调用.click()。即使它没有使用多个线程,它仍然在运行事件循环机制(可以将函数执行移动到不同的线程),因此我认为问题仍然是在线程之间移动异常,只是源和目标是相同的。您是否尝试过
sys.excepthook
?它将捕获该异常。print threading.currentThread()在.click()之前和def crash()内部返回相同的对象。(而且,一般来说,窗口架构是单线程的&事件驱动的。)tx-I确实使用sys.excepthook是错误的。然而。。。无论我在钩子里写了什么,我似乎都无法脱离事件处理程序。我必须放弃我的目标,写一个程序,如果它有一个未处理的异常就会死掉。我必须将我的目标降低到只在测试框架中充分捕获异常。因为测试已经有了一个框架,我不需要你的包装器。。。但是根本问题仍然没有答案——如何关闭这个PyQt特性。
def tearDown(self):
    self.assertTrue(self.no_exceptions)