[PyKDE] Exceptions and event loop (was: Web article on wxWindows and PyQt)

Sundance sundance at ierne.eu.org
Mon Oct 6 02:58:01 BST 2003


I heard Hans-Peter Jansen said:

> You could redirect stdout/stderr to an internal tee, which would
> trigger a PYSIGNAL, which in turn triggers a corresponding dialog.

I would *really* not want to go that way, if at all possible... I mean, 
having to parse a traceback for information, when an exception's 
traceback object already contains everything, would be a kludge 
unworthy of Python, frankly. :)

> Again, how a about throwing things together to provide a minimum
> example. I will try to help you as I can with the hairy parts ;)
> [I'm somewhat time restricted atm]

Here it goes.


---[ ExceptionHandler.py ]---------------------------------------------
from qt import *
import sys
import os.path

NAME = "MySoftware"


def bug(exception, traceback):
  
  line = traceback.tb_lineno
  filename = os.path.basename(traceback.tb_frame.f_code.co_filename)
  exception = str(exception)

  QMessageBox.critical(None, "Houston, we have a problem...",
      "Whoops. A critical error has occured. This is "
    + "most likely a bug in " + NAME + ". The error is:"
    + "<center><b><i>%s</i></b></center>" % exception
    + "It occured at <b>line %d</b> " % line
    + "of file <b>%s</b>." % filename
    + "<br><br>" + NAME + " will now close.<br>")

  mainwidget = qApp.mainWidget()

  if mainwidget:
    mainwidget.close()
  else:
    qApp.quit()


class MyWidget(QTextEdit):
  def keyPressEvent(self, *args):
    raise Exception, "Hiya! I'm a bug inside the event loop!"


app = QApplication(sys.argv)

try:
  somewidget = MyWidget()
  app.setMainWidget(somewidget)
  somewidget.show()
  raise Exception, "Hiya, I'm a bug outside the event loop!"
  app.exec_loop()

except Exception, err:
  dummy, exception, traceback = sys.exc_info()
  bug(exception, traceback)
-----------------------------------------------------------------------

There. This demonstrates what I'm trying to do.

When you run this code, it 'bugs correctly', so to speak -- the first 
exception gets caught, and the exception handler handles it, displays a 
nice friendly message, and when you click OK the app quits. I am very 
proud of this most professional-looking bug.

Now, comment the raise clause that sits outside the event loop, run the 
program again, and when the QTextEdit appears, try to type something 
inside it. Since we override the KeyPress event handler with something 
that raises an exception, well, that exception will be raised, 
obviously: the traceback is displayed in the terminal, and... nothing 
else. The event loop just swallows the exception, and our exception 
handler is never notified that an exception occured.

This is my problem, and it's fairly annoying. I'm pretty sure there 
exists a way to tell the PyQt event loop not to brush the exceptions 
under the carpet, since when an exception occurs you generally don't 
want to go on running like nothing happened, as the application state 
is now likely inconsistent, which might lead to data loss. Only, I have 
no idea how to tell that to the event loop.

> Switch comments in close/closeEvent methods to expose qApp.quit()
> and watch the different shut down paths.

Oh. Right. Thanks. =D

-- S.




More information about the PyQt mailing list