2013-08-06 65 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,沒有它你可以的做很多事情。