简体   繁体   English

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

[英]locals() and globals() in stack trace on exception (Python)

虽然堆栈跟踪在 Python 中很有用,但问题根源的数据通常会丢失——有没有办法确保至少将 locals()(可能还有 globals())添加到打印的堆栈跟踪中?

You can install your own exception hook and output what you need from there:您可以安装自己的异常钩子并从那里输出您需要的内容:

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()

To print vars from each frame in a traceback, change the above loop to要在回溯中打印每个帧的变量,请将上述循环更改为

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

This is a Box of Pandora.这是一盒潘多拉。 Values can be very large in printed form;打印形式的值可能非常大; printing all locals in a stack trace can easily lead to new problems just due to error output.在堆栈跟踪中打印所有局部变量很容易由于错误输出而导致新问题。 That's why this is not implemented in general in Python.这就是为什么这在 Python 中一般没有实现。

In small examples, though, ie if you know that your values aren't too large to be printed properly, you can step along the traceback yourself:但是,在小示例中,即如果您知道您的值不会太大而无法正确打印,您可以自己跟踪回溯:

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

The output will be sth like this:输出将是这样的:

  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}

And you can, of course, install your own except hook as thg435 suggested in his answer.当然,您可以按照他的回答中建议的 thg435 安装您自己的 except 钩子。

if you didn't know about this already, use the pdb post-mortem feature:如果您还不知道这一点,请使用 pdb post-mortem 功能:

x = 3.0
y = 0.0
print x/y
def div(a, b):
    return a / b
print div(x,y)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-3-d03977de5fc3> in div(a, b)
      1 def div(a, b):
----> 2     return a / b

ZeroDivisionError: float division

import pdb
pdb.pm()
> <ipython-input-3-148da0dcdc9e>(2)div()
      0     return a/b

ipdb> l
      1 def div(a,b):
----> 2     return a/b

ipdb> a
3.0
ipdb> b
0.0

etc.等。

there are cases where you really need the prints though, of course.当然,在某些情况下,您确实需要打印件。 you're better off instrumenting the code (via try/except) to print out extra information around a specific weird exception you are debugging than putting this for everything though, imho.您最好检测代码(通过 try/except)以打印出围绕您正在调试的特定奇怪异常的额外信息,而不是将其用于所有内容,恕我直言。

Try traceback-with-variables package.尝试带有变量的回溯包。

Usage:用法:

from traceback_with_variables import traceback_with_variables

def main():
    ...
    with traceback_with_variables():
        ...your code...

Exceptions with it:例外情况:

Traceback with variables (most recent call last):
  File "./temp.py", line 7, in main
    return get_avg_ratio([h1, w1], [h2, w2])
      sizes_str = '300 200 300 0'
      h1 = 300
      w1 = 200
      h2 = 300
      w2 = 0
  File "./temp.py", line 10, in get_avg_ratio
    return mean([get_ratio(h, w) for h, w in [size1, size2]])
      size1 = [300, 200]
      size2 = [300, 0]
  File "./temp.py", line 10, in <listcomp>
    return mean([get_ratio(h, w) for h, w in [size1, size2]])
      .0 = <tuple_iterator object at 0x7ff61e35b820>
      h = 300
      w = 0
  File "./temp.py", line 13, in get_ratio
    return height / width
      height = 300
      width = 0
builtins.ZeroDivisionError: division by zero

Installation:安装:

pip install traceback-with-variables

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM