The Python programming language has some useful flexibility which it can take a while to discover. One such example is exceptions. As programmers, we want as much relevant information as we can get when something goes unexpectedly wrong in our programs. When an unhandled exception bubbles up, Python's default behavior is to print a stack trace, the type of error, and an error description. This is printed to sys.stderr (i.e., the console window, typically), like this:
>>> 1/0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: integer division or modulo by zero
That's dead useful, yes, but perhaps in your program you'd really like to see some other specific data whenever there's a crash. For example, wouldn't it be great to see what the value of your current local variables are? Or the global variables too? Well, don't despair, Python has not left you out in the cold. In fact, the developers made it incredibly easy for you to send whatever you like to sys.stderr using a hook. Whenever an unhandled exception arises, this is the function that Python calls to do the printing:
sys.excepthook(type, value, traceback)
Which takes in these three values:
Note: these are the same three ordered values returned by sys.exc_info() during an exception
You can create your own function which takes the same three arguments, make it do what you like, and assign it to the hook:
>>> def my_exchandler(type, value, traceback): >>> print("Nothing to see here, folks. Everything's just fine. Move along.", file=sys.stderr) >>> # Note: The above is Python 3 code; Python 2's equivalent would look like this >>> # print >> sys.stderr, 'Some flippant message' >>> >>> import sys >>> sys.excepthook = my_exchandler >>> >>> 1/0 Nothing to see here, folks. Everything's just fine. Move along.
Or, if you wanted to display all the local and global variables as we mentioned before (which is slightly more useful than the above), do this:
>>> import sys, traceback >>> >>> def my_exchandler(type, value, tb): >>> # Warning: watch for a bit more Python 3-specific code below >>> traceback.print_exception(type, value, tb) >>> locals = True >>> for active_vars in [tb.tb_frame.f_locals, tb.tb_frame.f_globals]: >>> header = 'Locals:' if locals else 'Globals:' >>> print(header, file=sys.stderr) >>> for k, v in active_vars.items(): >>> if not (k.startswith('__') and k.endswith('__')): >>> print('\t{} = {}'.format(k, v), file=sys.stderr) >>> locals = False >>> >>> sys.excepthook = my_exchandler >>> >>> my_var = 'suspicious value here?' >>> >>> 1/0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: integer division or modulo by zero Locals: my_var = 'suspicious value here?' traceback = <module 'traceback' from '/usr/lib/python3.2/traceback.pyc'> my_exchandler = <function my_exchandler at 0x89f895c> sys= <module 'sys' (built-in)> Globals: my_var = 'suspicious value here?' traceback = <module 'traceback' from '/usr/lib/python2.7/traceback.pyc'> my_exchandler= <function my_exchandler at 0x89f895c> sys= <module 'sys' (built-in)>
Nice! But what happens then if you want the default behavior back, or if you completely mess up your replacement exception function and it produces an exception itself? Not to worry, Python kept a backup copy of the default hook the entire time, and uses it when needed. It's here:
sys.__excepthook__
You can use the backup copy to get back to the default behavior:
>>> sys.excepthook = sys.__excepthook__
Comments
Adam Groszer 6 years, 10 months ago
see the zope.exceptions package for a neat print_exception replacement
Link | ReplyNew Comment