Sundance wrote:
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.

_______________________________________________
PyKDE mailing list    [EMAIL PROTECTED]
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

  
Have a look at sys.excepthook

The attached code shows an example:

Ulli


#============================================================================#
# Catching exception in qt applications                                      #
#----------------------------------------------------------------------------#
import sys, string, traceback
from qt import *

#============================================================================#
# Exception handler that shows the traceback in a message box end exists the #
# application.                                                               #
#----------------------------------------------------------------------------#
def my_excepthook(exc_type, exc_value, exc_traceback):
    msg = string.joinfields(traceback.format_exception(exc_type,
                                                       exc_value,
                                                       exc_traceback))
    QMessageBox.critical(None,
                         app.tr("Critical Error"),
                         app.tr("An unexpected Excption has occured!\n"
                                "The Application will exit now.\n\n%1").arg(msg),
                         QMessageBox.Ok,
                         QMessageBox.NoButton,
                         QMessageBox.NoButton)

    # Call the default exception handler if you want
    sys.__excepthook__(exc_type, exc_value, exc_traceback)
    app.quit()

#============================================================================#
# Install the new exception handler, the default handler is always available #
# as sys.__excepthook__                                                      #
#----------------------------------------------------------------------------#
sys.excepthook = my_excepthook

#============================================================================#
# Main startup                                                               #
#----------------------------------------------------------------------------#
if __name__ == '__main__':  
    app = QApplication(sys.argv)
    ... 
    ...
    ...
    app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"));
    app.exec_loop()

#============================================================================#
# EOF                                                                        #
#----------------------------------------------------------------------------#

Reply via email to