views:

263

answers:

3

I'm using a PyQt4 user interface. I've redirected stderr to a log file for easy debugging and trouble-shooting, but now I need to display error messages to the user when an error occurs.

My issue is that I need to catch an exception when it happens and let the user know that it happened, but still let the traceback propagate to stderr (i.e. the log file).

If I do something like this:

def updateResults(self):
    try:
        #code that updates the results
    except:
        #display error message box

This will catch the exception and not propogate to the error log.

Is there some way to show the user the message and then continue to propogate the error?

Would this work?

except, e:
    #display error message box
    raise e

Is there a better way to accomplish my goal?

+3  A: 

Exactly, but you can just

raise

which will re-raise the currently handled exception.

Joe Koberg
+6  A: 

I think you are thinking about this in the wrong way. You shouldn't be re-raising the error simply to log it further down the line. The cannonical way of doing this in Python is to use the logging module. Adapted from the docs:

import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)

...

try:
    # code
except:
    logging.debug('Something bad happened', exc_info=True)
    # display message box
    # raise (if necessary)

This gives a far more flexible logging system than relying on errors produced on sys.stdout. You may not need to re-raise the exception if you can recover from the exception in some way.

Ant
I'll definitely use this method for future projects. Right now py2exe is doing the redirect of `stderr`, so unless I refactor my code to have try-except blocks around *every* function I'll end up with two log files (caught and un-caught exceptions).
tgray
Basically, the benefit of implementing this method isn't worth the refactoring time for *this* project.
tgray
Keep in mind (tgray) that you DO want to separate out your caught/uncaught exceptions. The logging schema that Ant describes is the best, because you can log to file, or log to database, or even log to file AND database, and you don't have to change your code in every place.
Also, because 'catch' blocks are very expensive (or 'except' in Python) you don't want to be raising exceptions just to log them, you should only raise an exception if your method has reached a dead-end. If it hasn't reached a dead-end, you should log it, and then gracefully continue or exit.
Duly noted. Thanks for the input.
tgray
+1  A: 

Some additional information:

(With PyQt4) you will also need to rebind sys.excepthook to your own function to catch all uncaught exceptions. Otherwise PyQt will just print them to the console, which may not be what you need...

import sys

def excepthook(exc_type, exc_val, tracebackobj):
    # do something useful with the uncaught exception
    ...

def main():
    # rebind excepthook
    sys.excepthook = excepthook
    ...
ChristopheD
Actually, py2exe handles this automatically creating a "program.exe.log" file.
tgray
But good to know if I ever write an application that isn't bundled with py2exe.
tgray