Phil Thompson schrieb:
Hello,
it seems that Python exceptions generated within event handlers do not get
propagated correctly. We use a sys.excepthook to abort gracefully with a
messagebox from our application, and this seems to work in most cases but
not within event handlers. For instance:
The old (ie. pre-SIP 4.2) behaviour was to call PyErr_Print() if an exception was raised in a Python re-implementation of a C++ virtual method. I never really liked this as it meant that the exception couldn't be caught with try/except.
In SIP 4.2 I removed the calls to PyErr_Print() and added a check for a Python exception after each called to a C++ method. The theory being that a try/except around the corresponding Python method call would catch any exception raised. There turned out to be two problems with this...
- The implementation was buggy. The SIP module was using exceptions in the meantime - it should have been saving and restoring any existing exception. With this fixed exceptions are caught properly.
- It only works if the C++ method returns to allow the test for the exception to be made. The one place where this doesn't happen is QApplication.exec_loop(). Therefore you still have to rely on providing your own sys.excepthook. However, it turns out that the excepthook is only called from within PyErr_Print().
So, rather than try and deal with the two conflicting requirements (being
able to catch as many exceptions as possible, and being able to detect
exceptions in exec_loop()) I plan to simply revert to the pre-SIP 4.2
behaviour - unless anybody has any other bright ideas.
To recapitulate:
1.) If a Python method, called asynchronous by QApplication.exec_loop() raises an exception, the surrounding C++ method checks this and has to use PyErr_Print() to trigger the excepthook (either the default or your own excepthook).
2.) If a Python method, called synchronous, raises an exceptions, the surrounding C++ method checks this and let the calling Python code handle this exception.
Why not inspect the calling frames? A method called asynchronous by QApplication.exec_loop() must have exec_loop() in one of it's outer frames, a method called synchronous outside the exec_loop doesn't have exec_loop() in its outer frames. It's just an idea, don't know if it could work.
Ulli
_______________________________________________ PyKDE mailing list PyKDE@mats.imk.fraunhofer.de http://mats.imk.fraunhofer.de/mailman/listinfo/pykde