有没有办法从发生异常的上下文中打印变量范围?
例如:
def f():
a = 1
b = 2
1/0
try:
f()
except:
pass # here I want to print something like "{'a': 1, 'b': 2}"
您可以使用函数
sys.exc_info()
来获取 except 子句中当前线程中发生的最后一个异常。这将是异常类型、异常实例和回溯的元组。回溯是框架的链表。这是解释器用来打印回溯的。它确实包含本地词典。
所以你可以这样做:
import sys
def f():
a = 1
b = 2
1/0
try:
f()
except:
exc_type, exc_value, tb = sys.exc_info()
if tb is not None:
prev = tb
curr = tb.tb_next
while curr is not None:
prev = curr
curr = curr.tb_next
print prev.tb_frame.f_locals
您必须首先提取回溯,在您的示例中,类似这样的内容会打印它:
except:
print sys.exc_traceback.tb_next.tb_frame.f_locals
我不确定 tb_next,我猜你必须经历完整的回溯,所以像这样(未经测试):
except:
tb_last = sys.exc_traceback
while tb_last.tb_next:
tb_last = tb_last.tb_next
print tb_last.tb_frame.f_locals
根据您的需要,有 2 种一般最佳实践。
只需编辑最少的代码即可打印变量
看看一些相关的包。对于简单的用法,你可以选择 traceback-with-variables (
pip install traceback-with-variables
),这是它的明信片
或者尝试tbvaccine,或better-exceptions,或任何其他包
以编程方式访问变量以在代码中使用它们
使用
inspect
模块
except ... as ...:
x = inspect.trace()[-1][0].f_locals['x']
Python 3 的零依赖解决方案:
import traceback
def format_traceback_with_locals(exc):
traceback_segments = traceback.format_exception(exc)
traceback_string = traceback_segments[0]
tb = exc.__traceback__
while tb is not None:
locals_dict = {k: v for k, v in tb.tb_frame.f_locals.items() if not k.startswith("__")}
traceback_segment = traceback.format_tb(tb)[0]
traceback_string += traceback_segment
traceback_string += " -> local variables: " + str(locals_dict) + "\n"
tb = tb.tb_next
traceback_string += traceback_segments[-1]
return traceback_string
用途:
try:
...
except Exception as e:
print(format_traceback_with_locals(e))
这会迭代回溯段(标题,然后是每个帧,最后是异常)并在每个帧后打印相应的局部变量。