Recipe 8.7. Starting the Debugger Automatically After an Uncaught Exception
Credit: Thomas Heller, Christopher Prinos, Syver Enstad,
Adam Hupp
Problem
When a script propagates an
exception, Python normally responds by printing a traceback and
terminating execution, but you would prefer to automatically enter an
interactive debugger in such cases when feasible.
Solution
By setting sys.excepthook, you can control what
happens when an uncaught exception propagates all the way up:
# code snippet to include in your sitecustomize.py
import sys
def info(type, value, tb):
if hasattr(sys, 'ps1') or not (
sys.stderr.isatty( ) and sys.stdin.isatty( )
) or issubclass(type, SyntaxError):
# Interactive mode, no tty-like device, or syntax error: nothing
# to do but call the default hook
sys._ _excepthook_ _(type, value, tb)
else:
import traceback, pdb
# You are NOT in interactive mode; so, print the exception...
traceback.print_exception(type, value, tb)
# ...then start the debugger in post-mortem mode
pdb.pm( )
sys.excepthook = info
Discussion
When Python runs a script and an uncaught exception is raised and
propagates all the way, a traceback is printed to standard error, and
the script terminates. However, Python exposes
sys.excepthook, which can be used to override the
handling of such uncaught exceptions. This lets you automatically
start the debugger on an unexpected exception when Python is not
running in interactive mode but a TTY-like device is available. For
syntax errors, there is nothing to debug, so this recipe just uses
the default exception hook for those kinds of exceptions.The code in this recipe is meant to be included in
sitecustomize.py, which Python automatically
imports at startup. Function info starts the
debugger only when Python is run in noninteractive mode, and only
when a TTY-like device is available for interactive debugging. Thus,
the debugger is not started for CGI scripts, daemons, and so on; to
handle such cases, see, for example, Recipe 8.5. If you do not have a
sitecustomize.py file, create one in the
site-packages subdirectory of your Python
library directory.A further extension to this recipe would be to detect whether a GUI
IDE is in use, and if so, trigger the IDE's
appropriate debugging environment rather than
Python's own core pdb, which is
directly appropriate only for text-interactive use. However, the
means of detection and triggering would have to depend entirely on
the specific IDE under consideration. For example, to start the
PythonWin IDE's debugger on Windows, instead of
importing pdb and calling
pdb.pm, you can import pywin
and call pywin.debugger.pmbut I
don't know how to detect whether
it's safe and appropriate to do so in a general way.
See Also
Recipe 8.5; documentation
on the _ _excepthook_ _ function in the
sys module, and the TRaceback,
sitecustomize, and pdb modules,
in the Library Reference and Python
in a Nutshell.