Morten Zilmer
Morten Zilmer

Reputation: 15924

Can exception handler get access to globals and locals variables at exception raise?

If a bug is detected in a Python program, it will be useful to generate a context dump including globals and locals variables, beside stack trace.

Is there some way the exception handler can get access to globals and locals, without having to include globals() and locals() in the raise exception statement ?

Example code below:

# Python 3.3 code
import sys

class FunError(Exception):
    pass

def fun(x):  # a can't be 2 or 4
    if x in [2, 4]:
        raise FunError('Invalid value of "x" variable')
    else:
        return(x ** 2)

try:
    print(fun(4))
except Exception as exc:
    # Is value of 'x' variable at time of exception accessible here ?
    sys.exit(exc)

Resulting exception code based on answers:

...
except FunError as exc:
    tb = sys.exc_info()[2]  # Traceback of current exception
    while tb.tb_next:  # Dig to end of stack
        tb = tb.tb_next  # Next level
    print('Local at raise exception: x =', tb.tb_frame.f_locals['x'])  # Wanted data
    sys.exit(exc)
...

Upvotes: 2

Views: 359

Answers (2)

msw
msw

Reputation: 43497

Easier and more straightforward than messing with stack frames is knowing that the variable you are interested in is in scope at the time of raise.

raise FunError('Invalid argument', x)

Also, you should never catch Exception, you should be as narrow as possible:

except FunError as e:
    print('I will not submit %d to fun()' % e[1])

is far preferred because except Exception will catch (among others) MemoryError or IndentationError, neither of which you can do much about.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1122132

The stack trace is a linked sequence of frame objects; each frame object has a reference to the globals and locals for that frame.

  • The traceback object has a tb_frame attribute, this is the 'current' frame.
  • The object also has a tb_next attribute, the link to the next traceback object in the stack.
  • Each frame object has f_globals and f_locals attributes, both are dictionaries.

The inspect module documentation has a handy overview of the attributes found on traceback and frame objects.

You may want to look over the traceback module; it provides a higher-level API to manipulate and display tracebacks.

Upvotes: 4

Related Questions