0

當我在上下文管理器中引發任何異常時,清理代碼未運行。例如:Python上下文管理器未清理

from contextlib import contextmanager 

try: 
    raise BaseException() 
except BaseException: 
    print "bye from except" 


@contextmanager 
def say_goodbye(): 
    yield 
    print "bye from context manager" 

with say_goodbye(): 
    raise BaseException() 

將輸出:

bye from except 
Traceback (most recent call last): 
    File "", line 15, in 
BaseException 

注意,在try /除了正確捕捉異常,而有說法沒有。 有什麼我不明白如何與聲明應該工作?

你可以看到這裏提琴代碼:http://pythonfiddle.com/context-manager-failing


僅供參考我在OSX小牛運行Python 2.7版。儘管我已經能夠在很多環境中進行復制,但我懷疑這與它有很大關係。

+0

這在['contextmanager'](https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager)文檔中有詳細說明。整個最後一段描述了它是如何工作的,告訴你如何使用'try /'except'或'try' /'finally'等。 – abarnert 2014-11-21 22:44:57

回答

7

你需要添加異常處理自己:

@contextmanager 
def say_goodbye(): 
    try: 
     yield 
    finally: 
     print "bye from context manager" 

以上,確保無論異常的finally塊始終運行裏面有塊。如果你想例外處理,你需要捕捉那些和可能再加註他們:

@contextmanager 
def say_goodbye(): 
    try: 
     yield 
    except Exception as exc: 
     print(exc) 
    finally: 
     print "bye from context manager" 

由於the documentation說:

如果塊中發生未處理的異常,它裏面的再加註發電機在產量發生點。因此,您可以使用try ... except ... finally語句來捕獲錯誤(如果有)或確保進行一些清理。

還要注意的是BaseException不是Exception

>>> isinstance(BaseException(), Exception) 
False 

自己的異常應該Exception,不BaseException繼承。