views:

179

answers:

4

Normally unhandled exceptions go to the stdout (or stderr?), I am building an app where I want to pass this info to the GUI before shutting down and display it to the user and, at the same time I want to write it to a log file. So, I need an str with the full text of the exception.

How can I do this?

A: 
try:
    # blah blah The Main Loop, function, whatever...
except e:
    do_something_with(str(e))
Ned Batchelder
I guess you mean "except Exception, e:" ...
Alex Martelli
+1  A: 
import sys, logging

logging.basicConfig(filename='/path/to/log/file', filemode='w')    
...

try:
   your_code_here()
except:
   logging.exception("My code failed") # logs exception to file
   # you define display_exception_in_ui as "def display_exception_in_ui(exc, tb):"
   display_exception_in_ui(*sys.exc_info()[1:]) # passes exception instance, traceback
Vinay Sajip
+5  A: 

Use sys.excepthook to replace the base exception handler. You can do something like:

import sys
from PyQt4 import QtGui

import os.path
import traceback

def handle_exception(exc_type, exc_value, exc_traceback):
  """ handle all exceptions """

  ## KeyboardInterrupt is a special case.
  ## We don't raise the error dialog when it occurs.
  if issubclass(exc_type, KeyboardInterrupt):
    if QtGui.qApp:
      QtGui.qApp.quit()
    return

  filename, line, dummy, dummy = traceback.extract_tb( exc_traceback ).pop()
  filename = os.path.basename( filename )
  error    = "%s: %s" % ( exc_type.__name__, exc_value )

  QtGui.QMessageBox.critical(None,"Error",
    "<html>A critical error has occured.<br/> "
  + "<b>%s</b><br/><br/>" % error
  + "It occurred at <b>line %d</b> of file <b>%s</b>.<br/>" % (line, filename)
  + "</html>")

  print "Closed due to an error. This is the full error report:"
  print
  print "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))
  sys.exit(1)



# install handler for exceptions
sys.excepthook = handle_exception

This catches all unhandled exceptions, so you don't need a try...except block at the top level of your code.

Neil
+3  A: 

You already got excellent answers, I just wanted to add one more tip that's served me well over the years in a variety of language for the specific problem "how to cleanly diagnose, log, etc, out of memory errors?". Problem is, if your code gets control before enough objects have been destroyed and their memory recycled, memory might be too tight to do propert logging, gui work, etc, etc -- how do we ensure this doesn't happen?

Answer: build an emergency stash so you know you can spend it in such emergencies:

rainydayfund = [[] for x in xrange(16*1024)]  # or however much you need

def handle_exception(e):
  global rainydayfund
  del rainydayfund
  ... etc, etc ...
Alex Martelli