2

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

异常处理程序是否可以通过某种方式访问​​全局变量和局部变量,而不必在引发异常语句中包含 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)
...
4

2 回答 2

4

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

  • 回溯对象有一个tb_frame属性,这是“当前”帧。
  • 该对象还有一个tb_next属性,即指向堆栈中下一个回溯对象的链接。
  • 每个框架对象都有f_globalsf_locals属性,都是字典。

inspect模块文档对 traceback 和 frame 对象上的属性有一个方便的概述。

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

于 2013-08-06T11:29:59.550 回答
1

比弄乱堆栈帧更容易和更直接的是知道你感兴趣的变量在raise 时就在范围内。

raise FunError('Invalid argument', x)

此外,你永远不应该捕获异常,你应该尽可能地窄:

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

是首选,因为except Exception会捕获(以及其他)MemoryError 或 IndentationError,这两者你都无能为力。

于 2013-08-06T11:44:30.580 回答