python - Exception handled surprisingly in Pyside slots -


problem: when exceptions raised in slots, invoked signals, not seem propagate usual through pythons call stack. in example code below invoking:

  • on_raise_without_signal(): handle exception expected.
  • on_raise_with_signal(): print exception , unexpectedly print success message else block.

question: reason behind exception being handled surprisingly when raised in slot? implementation detail/limitation of pyside qt wrapping of signals/slots? there read in docs?

ps: came across topic when got surprising results upon using try/except/else/finally when implementing qabstracttablemodels virtual methods insertrows() , removerows().


# -*- coding: utf-8 -*- """testing exception handling in pyside slots.""" __future__ import unicode_literals, print_function, division  import logging import sys  pyside import qtcore pyside import qtgui   logging.basicconfig(level=logging.debug) logger = logging.getlogger(__name__)   class exceptiontestwidget(qtgui.qwidget):      raise_exception = qtcore.signal()      def __init__(self, *args, **kwargs):         super(exceptiontestwidget, self).__init__(*args, **kwargs)          self.raise_exception.connect(self.slot_raise_exception)          layout = qtgui.qvboxlayout()         self.setlayout(layout)          # button invoke handler handles raised exception expected         btn_raise_without_signal = qtgui.qpushbutton("raise without signal")         btn_raise_without_signal.clicked.connect(self.on_raise_without_signal)         layout.addwidget(btn_raise_without_signal)          # button invoke handler handles raised exception via signal unexpectedly         btn_raise_with_signal = qtgui.qpushbutton("raise signal")         btn_raise_with_signal.clicked.connect(self.on_raise_with_signal)         layout.addwidget(btn_raise_with_signal)      def slot_raise_exception(self):         raise valueerror("valueerror on purpose")      def on_raise_without_signal(self):         """call function raises exception directly."""         try:             self.slot_raise_exception()         except valueerror exception_instance:             logger.error("{}".format(exception_instance))         else:             logger.info("on_raise_without_signal() executed successfully")      def on_raise_with_signal(self):         """call slot raises exception via signal."""         try:             self.raise_exception.emit()         except valueerror exception_instance:             logger.error("{}".format(exception_instance))         else:             logger.info("on_raise_with_signal() executed successfully")   if (__name__ == "__main__"):     application = qtgui.qapplication(sys.argv)      widget = exceptiontestwidget()     widget.show()      sys.exit(application.exec_()) 

as you've noted in question, real issue here treatment of unhandled exceptions raised in python code executed c++. not signals: affects reimplemented virtual methods well.

in pyside, pyqt4, , pyqt5 versions 5.5, default behaviour automatically catch error on c++ side , dump traceback stderr. normally, python script automatically terminate after this. not happens here. instead, pyside/pyqt script carries on regardless, , many people quite rightly regard bug (or @ least misfeature). in pyqt-5.5, behaviour has been changed qfatal() called on c++ side, , program abort normal python script would. (i don't know current situation pyside2, though).

so - should done this? best solution versions of pyside , pyqt install exception hook - because take precedence on default behaviour (whatever may be). unhandled exception raised signal, virtual method or other python code firstly invoke sys.excepthook, allowing customise behaviour in whatever way like.

in example script, mean adding this:

def excepthook(cls, exception, traceback):     print('calling excepthook...')     logger.error("{}".format(exception))  sys.excepthook = excepthook 

and exception raised on_raise_with_signal can handled in same way other unhandled exceptions.

of course, imply best practice pyside/pyqt applications use largely centralised exception handling. includes showing kind of crash-dialog user can report unexpected errors.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -