2013-08-06 37 views
2

如果在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) 
... 

回答

4

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

  • 回溯对象具有tb_frame属性,这是'当前'框架。
  • 该对象还具有tb_next属性,链接到下一个回溯对象在堆栈中。
  • 每个框架对象都有f_globalsf_locals属性,都是字典。

inspect module documentation有一个方便的回溯和框架对象上的属性概述。

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

+0

也感谢您参考其他文档。真的让人惊讶,Python可以提供什么! –

1

比堆栈框架更容易和更直接的是知道你在感兴趣的变量是在提高时的范围。

raise FunError('Invalid argument', x) 

此外,你应该永远赶不上异常,你应该尽可能窄:

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

远远首选,因为except Exception将赶上(等等)的MemoryError或IndentationError,没有它你可以的做很多事情。