[英]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.