How can I extract local variables from a stack trace?

前端 未结 3 1210
深忆病人
深忆病人 2021-01-05 01:22

Suppose I have a function that raises unexpected exceptions, so I wrap it in ipdb:

def boom(x, y):
    try:
        x / y
    except Exception as e:
                 


        
相关标签:
3条回答
  • 2021-01-05 01:52

    Depending on what you need, there are 2 general best practices.

    Just print the variables with minimal code edits

    Have a look at some related packages. For simple usage you might pick traceback-with-variables (pip install traceback-with-variables), here is it's postcard

    Or try tbvaccine, or better-exceptions, or any other package

    Programmatically access variables to use them in your code

    Use inspect module

    except ... as ...:
        x = inspect.trace()[-1][0].f_locals['x']
    

    What about debugger?

    Debugger is made for step-by-step execution and breakpoints. Using it to inspect exception reasons is really inconvenient and should be avoided. You can automate your debug session using two mentioned best practices.

    0 讨论(0)
  • 2021-01-05 01:59

    You can also use the context manager

    with ipdb.launch_ipdb_on_exception():
        main()
    

    It's an easy-to-use wrapper using ipdb.post_mortem.

    0 讨论(0)
  • 2021-01-05 02:09

    Turns out that it is possible to extract variables from a traceback 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 do post-mortem debugging on that 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 gets us straight to the offending code:

    > /tmp/crash.py(4)boom()
          3 def boom(x, y):
    ----> 4     x / y
          5 
    
    ipdb> p x
    2
    
    0 讨论(0)
提交回复
热议问题