异常(Python)中的堆栈跟踪中的locals()和globals()

Let*_*t4U 10 python exception stack-trace

虽然堆栈跟踪在Python中很有用,但大多数情况下问题根源的数据都缺失了 - 有没有办法确保至少将locals()(以及可能的globals())添加到打印的堆栈跟踪中?

geo*_*org 13

您可以安装自己的异常挂钩并从那里输出所需内容:

import sys, traceback

def excepthook(type, value, tb):
    traceback.print_exception(type, value, tb)

    while tb.tb_next:
        tb = tb.tb_next

    print >>sys.stderr, 'Locals:',  tb.tb_frame.f_locals
    print >>sys.stderr, 'Globals:', tb.tb_frame.f_globals

sys.excepthook = excepthook

def x():
    y()

def y():
    foo = 1
    bar = 0

    foo/bar

x()
Run Code Online (Sandbox Code Playgroud)

要在回溯中从每个帧打印变量,请将上面的循环更改为

    while tb:
        print >>sys.stderr, 'Locals:',  tb.tb_frame.f_locals
        print >>sys.stderr, 'Globals:', tb.tb_frame.f_globals
        tb = tb.tb_next
Run Code Online (Sandbox Code Playgroud)


Alf*_*lfe 5

这是潘多拉魔盒。印刷形式的值可能非常大;在堆栈跟踪中打印所有本地变量很容易由于错误输出而导致新问题。这就是为什么这在 Python 中一般不实现的原因。

不过,在小示例中,即如果您知道您的值不太大而无法正确打印,则可以自己逐步进行回溯:

import sys
import traceback

def c():
  clocal = 1001
  raise Exception("foo")

def b():
  blocal = 23
  c()

def a():
  alocal = 42
  b()

try:
  a()
except Exception:
  frame = sys.exc_info()[2]
  formattedTb = traceback.format_tb(frame)    
  frame = frame.tb_next
  while frame:
    print formattedTb.pop(0), '\t', frame.tb_frame.f_locals
    frame = frame.tb_next
Run Code Online (Sandbox Code Playgroud)

输出将是这样的:

  File "/home/alfe/tmp/stacktracelocals.py", line 19, in <module>
    a()
        {'alocal': 42}
  File "/home/alfe/tmp/stacktracelocals.py", line 16, in a
    b()
        {'blocal': 23}
  File "/home/alfe/tmp/stacktracelocals.py", line 12, in b
    c()
        {'clocal': 1001}
Run Code Online (Sandbox Code Playgroud)

当然,您可以按照 thg435 在他的回答中建议的那样安装自己的 except 钩子。