异常处理程序可以在异常引发时访问全局变量和本地变量吗?

时间:2013-08-06 11:29:15

标签: python python-3.x

如果在Python程序中检测到错误,那么在堆栈跟踪旁边生成包括全局变量和局部变量的上下文转储会很有用。

异常处理程序是否有某种方式可以访问全局变量和局部变量,而不必在raise异常语句中包含globals()和locals()?

以下示例代码:

# Python 3.3 code
import sys

class FunError(Exception):
    pass

def fun(x):  # a can't be 2 or 4
    if x in [2, 4]:
        raise FunError('Invalid value of "x" variable')
    else:
        return(x ** 2)

try:
    print(fun(4))
except Exception as exc:
    # Is value of 'x' variable at time of exception accessible here ?
    sys.exit(exc)

基于答案产生的异常代码:

...
except FunError as exc:
    tb = sys.exc_info()[2]  # Traceback of current exception
    while tb.tb_next:  # Dig to end of stack
        tb = tb.tb_next  # Next level
    print('Local at raise exception: x =', tb.tb_frame.f_locals['x'])  # Wanted data
    sys.exit(exc)
...

2 个答案:

答案 0 :(得分:4)

堆栈跟踪是帧对象的链接序列;每个帧对象都引用该帧的全局变量和局部变量。

  • traceback对象具有tb_frame属性,这是“当前”框架。
  • 该对象还有一个tb_next属性,指向堆栈中 next traceback对象的链接。
  • 每个框架对象都有f_globalsf_locals属性,两者都是字典。

inspect module documentation可以方便地概述在回溯和框架对象上找到的属性。

您可能需要查看traceback module;它提供了一个更高级别的API来操作和显示回溯。

答案 1 :(得分:1)

比使用堆栈帧更容易和更直接的是知道在加注时你对感兴趣的变量在范围内。

raise FunError('Invalid argument', x)

此外,你永远不应该捕捉异常,你应该尽可能地缩小:

except FunError as e:
    print('I will not submit %d to fun()' % e[1])

是首选,因为except Exception会捕获(其中包括)MemoryError或IndentationError,这两者都无法解决。