0

我想在执行 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()参数。

有谁知道如何获取被调用者命名空间?

4

1 回答 1

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 文档的第 3.2 节中有更多关于tracebackframe对象的信息。


更新

这与上面的对象相同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"
于 2013-06-01T14:46:27.227 回答