How to extract local variables from stack trace?

Suppose I have a function that throws unexpected exceptions, so I am moving it to ipdb:

def boom(x, y): try: x / y except Exception as e: import ipdb; ipdb.set_trace() def main(): x = 2 y = 0 boom(x, y) if __name__ == '__main__': main() 

I can move the stack to find out what x and y values ​​have:

 $ python crash.py > /tmp/crash.py(6)boom() 5 except Exception as e: ----> 6 import ipdb; ipdb.set_trace() 7 ipdb> u > /tmp/crash.py(11)main() 10 y = 0 ---> 11 boom(x, y) 12 ipdb> py 0 

However, when debugging, I just want to postpone the debugger at the top level:

 def boom(x, y): x / y def main(): x = 2 y = 0 boom(x, y) if __name__ == '__main__': try: main() except Exception as e: import ipdb; ipdb.set_trace() 

I can display the trace, but I cannot view the variables inside the called function:

 $ python crash.py > /tmp/crash.py(14)<module>() 12 main() 13 except Exception as e: ---> 14 import ipdb; ipdb.set_trace() ipdb> !import traceback; traceback.print_exc(e) Traceback (most recent call last): File "crash.py", line 12, in <module> main() File "crash.py", line 8, in main boom(x, y) File "crash.py", line 3, in boom x / y ZeroDivisionError: integer division or modulo by zero ipdb> d # I want to see what value x and y had! *** Newest frame 

The exception object still has stack references when an exception occurs. Can I access x and y here even if the stack has broken up?

+5
source share
1 answer

It turns out that you can extract variables from the trace object.

To manually extract values:

 ipdb> !import sys ipdb> !tb = sys.exc_info()[2] ipdb> p tb.tb_next.tb_frame.f_locals {'y': 0, 'x': 2} 

Even better, you can use an exception to explicitly debug this stack:

 import sys def boom(x, y): x / y def main(): x = 2 y = 0 boom(x, y) if __name__ == '__main__': try: main() except Exception as e: # Most debuggers allow you to just do .post_mortem() # but see https://github.com/gotcha/ipdb/pull/94 tb = sys.exc_info()[2] import ipdb; ipdb.post_mortem(tb) 

Which brings us straight to the offending code:

 > /tmp/crash.py(4)boom() 3 def boom(x, y): ----> 4 x / y 5 ipdb> px 2 
+3
source

Source: https://habr.com/ru/post/1246969/


All Articles