0

Is there a convenient way to get a more detailed stack trace on a Python exception? I'm hoping to find a wrapper utility/module or some other way to get a bit more info from the stack trace without having to actually modify the Python script that generates it. I'd like to be able to use this when running unit tests, or doctests, or when running utilities or inline scripts from the shell.

Specifically I think I'd like to have the values of local variables, or maybe just the values of the arguments passed to the innermost function in the stack trace. Some options to set the detail level would be nifty.

intuited
  • 23,174
  • 7
  • 66
  • 88

3 Answers3

2

Not specifically related to your problem, but you might find this code useful -- automatically starts up the python debugger when a fatal exception occurs. Good for working with interactive code. It's originally from ActiveState

# 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
synthesizerpatel
  • 27,321
  • 5
  • 74
  • 91
  • Hey, thanks for that. I ended up wrapping your code in a [module](http://pypi.python.org/pypi/coroner) to make it convenient to invoke pdb debugging with `python -m coroner some_script.py`. Umm, hope that's okay? I gave you attribution in the docs. I will probably change the module later to spit out stack traces like I want them so I don't have to dig them out with pdb, and so I can use it for unit tests and such. In the meantime, though, this might be useful to somebody. – intuited Oct 12 '10 at 08:20
  • Hey, you can do this with `ipython` too, I just realized. You pass the `-pdb` option before passing `-c ...` or a filename. It doesn't seem to support `-m ...` but maybe it could be made to do that by passing `/usr/lib/python../runpy.py` as the filename. – intuited Oct 12 '10 at 08:43
0

Did you have a look at traceback module?

Also on SO:

Community
  • 1
  • 1
pyfunc
  • 65,343
  • 15
  • 148
  • 136
0

As mentionned by pyfunc, you can use the function in the traceback module but you only get a stacktrace.

If you want to inspect the stack you have to use the sys.exc_info() function and walk the traceback member and dump information from its frame (tb_frame). See the python Reference Manual for further information on these types.

Here is an example:

def killit(a):
    a[10000000000000] = 1

def test(a):
    killit(a)

def iterate_traceback(tb):
    while tb is not None:
        yield tb
        tb = tb.tb_next

try:
    test(tuple())
except Exception as e:

    import sys
    exception_info = sys.exc_info()

    traceback = exception_info[2]
    for tb in iterate_traceback(traceback):
        print "-" * 10
        print tb.tb_frame.f_code
        print tb.tb_frame.f_locals
        print tb.tb_frame.f_globals
Community
  • 1
  • 1
Rod
  • 52,748
  • 3
  • 38
  • 55