PyQt的事件处理程序SNARF例外(PyQt event handlers snarf excep

2019-07-18 15:21发布

下面是说明了这个问题的代码:

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中的默认的错误处理,这样我就可以传播或错误记录自己? 请不要回答sys.excepthook,无论是-它抓住的是PyQt4中没有捕获错误。

Answer 1:

这是不是问题的答案,你傻的网站。 停止迫使我们融入一个理想化的线程模板的先入为主的观念。

未回答是用我的测试框架设置()中的异常处理程序挂钩:

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 =假”,我更愿意简单地说self.fail(“”)。 然而,由于Python的单元测试库上抛出异常的坚持只是注册测试失败,因为PyQt的上snarfing 所有异常坚持,我们有一个僵局。

要适应一个理想化的测试用例unittest.TestCase生成的傻先入为主的概念,我有,而不是设置一个变量,然后检测其在拆卸:

def tearDown(self):
    self.assertTrue(self.no_exceptions)

这仍然不是很理想,但至少它会迫使我花更多的时间关注的错误,而不是花费当时的技术网站上抱怨他们。

根的问题:如何关闭的PyQt的魔力错误处理程序? - 仍然没有答案......



Answer 2:

我认为答案是,这是不是一个“功能” PyQt ,而是一个固有的,它允许信号/插槽工作设计结果(记住,信号/时隙通信正在经历一个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'

这将不打印“不应该发生”,并给你的东西与你的自动化测试赶上(用正确的异常类型)。

In [11]: Traceback (most recent call last):
  File "/tmp/ipython2-3426rwB.py", line 68, in crash
Exception: Crash!
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-11-6ef4090ab3de> in <module>()
----> 1 execfile(r'/tmp/ipython2-3426rwB.py') # PYTHON-MODE

/tmp/ipython2-3426rwB.py in <module>()

/tmp/ipython2-3426rwB.py in new_fun(*args, **kwargs)

Exception: Crash!

In [12]: 

堆栈跟踪被抬高了,但你仍然可以读取被打印出来的第一个。



文章来源: PyQt event handlers snarf exceptions