How can you programmatically inspect the stack trace of an exception in Python?
Asked Answered
Y

5

20

When an exception occurs in Python, can you inspect the stack? Can you determine its depth? I've looked at the traceback module, but I can't figure out how to use it.

My goal is to catch any exceptions that occur during the parsing of an eval expression, without catching exceptions thrown by any functions it may have called. Don't berate me for using eval. It wasn't my decision.

NOTE: I want to do this programmatically, not interactively.

Youngman answered 1/3, 2010 at 21:37 Comment(0)
R
6

You can use the inspect module which has some utility functions for tracing. Have a look at the overview of properties of the frame objects.

Riddell answered 1/3, 2010 at 21:43 Comment(0)
T
14

traceback is enough - and I suppose that documentation describes it rather well. Simplified example:

import sys
import traceback

try:
    eval('a')
except NameError:
    traceback.print_exc(file=sys.stdout)
Tetracaine answered 1/3, 2010 at 22:20 Comment(2)
I'm not trying to print the traceback. I'm trying to inspect it. How does this tell me whether the exception occurred in the eval text itself, or in a function called by the evaluated text?Youngman
Many different kinds of errors can be thrown if the eval text is wrong. I ended up using inspect and looking at the depth of the traceback to see if the error was caused by evaluating the original text, or if it was in the body of a called function.Youngman
R
6

You can use the inspect module which has some utility functions for tracing. Have a look at the overview of properties of the frame objects.

Riddell answered 1/3, 2010 at 21:43 Comment(0)
C
5

I like the traceback module.

You can get a traceback object using sys.exc_info(). Then you can use that object to get a list preprocessed list of traceback entries using traceback.extract_tb(). Then you can get a readable list using traceback.format_list() as follows:

import sys
import traceback, inspect

try:
    f = open("nonExistant file",'r')
except:
    (exc_type, exc_value, exc_traceback) = sys.exc_info()
    #print exception type
    print exc_type
    tb_list = traceback.extract_tb(sys.exc_info()[2])
    tb_list = traceback.format_list(tb_list)
    for elt in tb_list:
        print elt
        #Do any processing you need here.

See the sys Module: http://docs.python.org/library/sys.html

and the traceback Module: http://docs.python.org/library/traceback.html

Chlor answered 27/11, 2011 at 16:30 Comment(0)
K
2

You define such a function (doc here):

def raiseErr():
   for f in inspect.stack(): print '-', inspect.getframeinfo(f[0])

and call it from your modules so:

raiseErr()

The function raiseErr will print info about the place you called it.

More elaborate, you can do so:

import inspect, traceback
A = [inspect.getframeinfo(f[0]) for f in inspect.stack()]
print "traceback structure fields:", filter(lambda s: s[0] != '_', dir(A[0]))
print A[0].filename, A[0].lineno
for f in inspect.stack():
    F = inspect.getframeinfo(f[0])
    print '-', F.filename, F.lineno, '\t', F.code_context[0].strip()

Other possibility is to define this function:

def tr():
    print '* - '*10,
    print sys._getframe(1).f_code.co_name

And call it in the place where you want the trace. If you want all the trace, make an iterator from 1 up in _getframe(1).

Ker answered 30/3, 2013 at 17:31 Comment(0)
A
0

In addition to AndiDog's answer about inspect, note that pdb lets you navigate up and down the stack, inspecting locals and such things. The source in the standard library pdb.py could be helpful to you in learning how to do such things.

Ayeshaayin answered 2/3, 2010 at 2:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.