How can I see the details of an exception in Python's debugger?

Question:

Sometimes while I’m debugging an exception will be raised.

For example, consider this code:

def some_function():  # Pretend this function is in a library...
    # ...and deep within the library is an exception:
    raise Exception('An exception message with valuable information.')

import pdb; pdb.set_trace()
try:
    some_function()  # Pretend I am debugging from this point using pdb.
except:
    pass

While debugging from the some_function() call, if I issue a next command I will see the following details about the exception that was raised [and caught]:

Exception: Exceptio...ation.',)

Here’s a straight copy / paste from the terminal I was working in:

> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) next
Exception: Exceptio...ation.',)
> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) 

It would be useful to see the entire exception message. How can I do this in pdb?

Asked By: Buttons840

||

Answers:

The python debugger doesn’t “break on exception” – which can be quite frustrating if you’re used to that functionality. As such, I adopt a policy of logging strack traces and working back from there.

import logging
try:
    raise Exception('An exception message with valuable information.')
except:
    logging.exception('Error in test code')

If you use a good IDE (such as Eclipse with pydev), the log entries for the stacktrace are made into hyperlinks that jump straight to the appropriate position in code.

You can dump a stack trace at any point in your code by importing traceback

import traceback
trace = traceback.format_exc()
Answered By: Steve Mayne

pdb stores the exception type and value in __exception__. You can print the exception part of a traceback in pdb with:

import traceback; print "".join(traceback.format_exception_only(*__exception__))

For example:

> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) next
Exception: Exceptio...ation.',)
> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) import traceback; print "".join(traceback.format_exception_only(*__exception__))
Exception: An exception message with valuable information.

(Pdb) 

Unfortunately this does not include the rest of the traceback, but all that information is available through the where command of pdb anyway. If you really want the full traceback, you can add the following to your ~/.pdbrc file or paste it into your terminal:

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack
!global __format_exception_only, __print_stack; from traceback import format_exception_only as __format_exception_only, print_stack as __print_stack
!global __Pdb; from pdb import Pdb as __Pdb

# find the last frame on the stack with an object named "pdb" or "self" that is a pdb.Pdb object
# works for pdb called the usual way, or pdb.pm(), or pdb.set_trace()
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1]

alias traceback __print_stack(__pdb.stack[-1][0]); print "".join(__format_exception_only(*__exception__))

Then you can just use the new traceback alias to get what you want:

> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) next
Exception: Exceptio...ation.',)
> /tmp/test.py(7)<module>()
-> some_function()  # Pretend I am debugging from this point using pdb.
(Pdb) traceback
  File "test.py", line 7, in <module>
    some_function()  # Pretend I am debugging from this point using pdb.
  File "test.py", line 3, in some_function
    raise Exception('An exception message with valuable information.')
Exception: An exception message with valuable information.

(Pdb) 

Warning: all of this relies on undocumented pdb and bdb internals and is likely to break.

Answered By: Michael Hoffman
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.