我可以获取抛出异常的Python函数的局部变量吗?

dav*_*gan 23 python exception-handling

我正在为项目编写自定义日志记录系统.如果函数抛出异常,我想记录它的局部变量.是否可以从捕获异常的except块访问raise函数的局部变量?例如:

def myfunction():
    v1 = get_a_value()
    raise Exception()

try:
    myfunction()
except:
    # can I access v1 from here?
Run Code Online (Sandbox Code Playgroud)

Dav*_*d Z 32

如果你知道你的异常处理代码需要它,那么将值传递给异常通常是更简洁的设计.但是,如果您正在编写调试器或类似的东西,您将需要访问变量而不知道它们是哪些变量,您可以在抛出异常的上下文中访问任意变量:

def myfunction():
    v1 = get_a_value()
    raise Exception()

try:
    myfunction()
except:
    # can I access v1 from here?
    v1 = inspect.trace()[-1][0].f_locals['v1']
Run Code Online (Sandbox Code Playgroud)

模块文档中描述了trace函数的功能以及traceback它处理的对象的格式.inspect

  • `inspect.trace`是解释器堆栈的更高级别接口.但它在幕后使用`sys.exc_info`.(实现是`return getinnerframes(sys.exc_info()[2],context)`.)虽然我不会说任何一种方式都必须_incorrect_,但是使用`inspect`的功能可能是更好的形式,因为你不要我不得不担心实施细节,而且它会让你更清楚你实际在做什么. (2认同)

Gui*_*fay 7

您可以在框架对象中查找局部变量,您可以从 中获取该变量sys.exc_info

>>> import sys
>>> def f(a):
...     b = a - 1
...     print 1.0 / b
...
>>> try:
...     f(1)
... except Exception, e:
...     print sys.exc_info()[2].tb_next.tb_frame.f_locals
...
{'a': 1, 'b': 0}
Run Code Online (Sandbox Code Playgroud)

您必须包含适当数量的tb_nexts,具体取决于抛出异常的堆栈深度。