PyQt snarf event handler exceptions

Here is the code that illustrates the problem:

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' 

When I run this, PyQt4 handles the error for me. My console displays a stack trace using "Crash!" etc., and I see: "I must not happen."

This is not useful because I was given a large application with many handlers, and I need to push all my errors into my face (and into my - ahm - automated tests). Every time I run, errors go out of my networks, and they require an excessive and useless attempt: besides the blocks inside each handler, just to catch them all.

In other words, I want good code to be very good, and bad code to be very bad. Not whitewashed.

Sorry if this is already set, but when I look for it, I naturally get thousands of newcomers who ask basic error handling questions (or, even worse, I get newcomers asking how to disable their wayward exceptions !;)

How to override PyQt4 default error handling, so I can distribute or report errors myself? And please do not respond to sys.excepthook, either - it catches errors that PyQt4 does not catch.

+6
source share
2 answers

This is not an answer, you are a dumb site. Stop making us fit into the preconceived notion of a perfect thread pattern.

Failure to use my test environment setUp () to bind an exception handler:

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

If it says "self.no_exceptions = False", I would rather simply say self.fail (''). However, due to the fact that the Python unit test library insists on eliminating exceptions only for recording test errors, and also because PyQt insists on cutting all exceptions, we have a dead end.

To fit into unittest.TestCase's silly biased notion of an idealized test case, I have to set the variable instead and then detect it in teardown mode:

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

This is still not perfect, but at least it will make me spend more time paying attention to errors, instead of wasting time complaining about them on technical websites.

Root question: how to disable PyQt error handler? - remains unanswered ...

+3
source

I think the answer is that this is not a PyQt “function”, but a consequence inherent in the design, which allows working with signals / slots (remember that the signal / slot connection passes through the C ++ layer as a).

This is ugly, but helps a little and ends your problem.

 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' 

This will not print “should not be” and gives you something that can be caught using automatic tests (with the correct type of exception).

 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]: 

The stack trace goes up, but you can still read the first one that was printed.

+2
source

All Articles