Reputation: 15924
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
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
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.
tb_frame
attribute, this is the 'current' frame.tb_next
attribute, the link to the next traceback object in the stack.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