When Python runs a script and an uncatched exception is raised, a traceback is printed and the script is terminated. Python2.1 has introduced sys.excepthook, which can be used to override the handling of uncaught exceptions. This allows to automatically start the debugger on an unexpected exception, even if python is not running in interactive mode.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# code snippet, to be included in 'sitecustomize.py' import sys def info(type, value, tb): if hasattr(sys, 'ps1') or not sys.stderr.isatty(): # we are in interactive mode or we don't have a tty-like # device, so we call the default hook sys.__excepthook__(type, value, tb) else: import traceback, pdb # we are NOT in interactive mode, print the exception... traceback.print_exception(type, value, tb) print # ...then start the debugger in post-mortem mode. pdb.pm() sys.excepthook = info
The above code should be included in 'sitecustomize.py', which is automatically imported by python. The debugger is only started when python is run in non-interactive mode.
If you have not yet a 'sizecustomize.py' file, create one and place it somewhere on your pythonpath.
Gui debugger? This is a great idea; I'd love to use it under the PythonWin gui debugger. Any way to make that happen?
I'm using Python as the Active Script language for IIS/ASP, and would love to throw the errors into the PythonWin debugger.
using pywin debugger. instead of:
import pdb pdb.pm()
import pywin.debugger pywin.debugger.pm()
Some small improvements. It is nice to check if the exception is a syntax error because SyntaxError's can't be debugged.
Also nice is just assigning the debug exception hook when the program is run is debug mode.
Should check if stdin.isatty also. If stdin isn't a tty (e.g. a pipe) and this gets called the pdb code will just start printing it's prompt continually instead of giving a useful traceback. Changing the test to "not (sys.stderr.isatty() and sys.stdin.isatty())" fixes it.
Addidtional check: sys.stdout.isatty(). If the standart output is redirected to a file, then you might not want to start the debugger, because you do not see the debugger's output. Under consideration of the previous comments the condition has to be changed to:
if hasattr(sys, 'ps1') or not sys.stderr.isatty() or not sys.stdin.isatty() or not sys.stdout.isatty() or type==SyntaxError:
Note, sometimes sys.excepthook gets redefined by other modules, for instance if you are using IPython embedded shell. In this case, insert following after all the imports in your script
from sitecustomize import info sys.excepthook=info
I've collected the comments here in my gist: https://gist.github.com/rctay/3169104