我想拦截异常并在执行Python代码时执行一些报告。主要是我想在发生异常时导出代码的命名空间。
我能做的是:
我有文件test.py
会引发异常:
for i in range(10):
if i > 5:
j
else:
i
文件check.py
将拦截异常并在测试脚本作为参数传递时启动调试器:
import sys, pdb
try:
__import__(sys.argv[1])
except Exception as e:
pdb.post_mortem(sys.exc_info()[2])
那太好了。
此外,我可以使用inspect
模块找到发生异常的被调用者中的帧:
import sys, inspect
try:
__import__(sys.argv[1])
except Exception as e:
callee_frame_tuple = inspect.trace()[1]
print callee_frame_tuple
输出:
(<frame object at 0x00C9B260>, 'C:\\Temp\\test.py', 3, '<module>', [' j\n'], 0)
并使用它来获取有关getargvalues()
的框架的信息:
import sys, inspect
try:
__import__(sys.argv[1])
except Exception as e:
callee_frame_tuple = inspect.trace()[1]
inspect.getargvalues(callee_named_tuple[0])[3]['__builtins__']['locals']()
输出:
{'__builtins__': <module '__builtin__' (built-in)>,
'__doc__': None,
'__file__': 'C:\\Temp\\check.py',
'__name__': '__main__',
'__package__': None,
'e': NameError("name 'j' is not defined",),
'inspect': <module 'inspect' from 'C:\Python27\lib\inspect.pyc'>,
'sys': <module 'sys' (built-in)>}
所以我得到了check.py
的本地人而不是被叫者test.py
的本地人,尽管我把它的帧参考用作getargvalues()
参数。
有谁知道如何获得被调用者名称空间?
答案 0 :(得分:1)
从Python打印的格式化回溯中不清楚,但由于您使用的是__import__
,因此您实际上会获得两个单独的traceback
个对象。您可以像这样访问第二个......
import sys
from pprint import pprint
try:
__import__(sys.argv[1])
except Exception as e:
my_traceback = sys.exc_info()[2]
# Print locals for my stack frame
#pprint(my_traceback.tb_frame.f_locals)
# Print locals for other stack frame
other_traceback = my_traceback.tb_next
pprint(other_traceback.tb_frame.f_locals)
有关Python文档section 3.2中traceback
和frame
个对象的更多信息。
<强>更新强>
你是对的。我对这与
inspect.getargvalues(callee_named_tuple[0])
的对象相同 上面,所以我不知道这实际上是被叫当地人,而我 深入研究。
inspect
模块并不熟悉 - 我倾向于直接访问traceback
属性。
我原以为我可以找到
i
变量所在的命名空间字典 值6然后发生异常,这样我得到i=None
。是 有没有办法获得被调用者的命名空间?
我也注意到了。使用__import__
似乎有点奇怪,因为它在使用execfile()
时工作正常。以下脚本......
import sys
try:
execfile(sys.argv[1])
except Exception as e:
the_value_of_i = sys.exc_info()[2].tb_next.tb_frame.f_locals['i']
print 'The value of "i" was "%r"' % the_value_of_i
... ...产量
The value of "i" was "6"