我們還沒有談到__exit__
方法的這三個參數(shù):type
, value
和traceback
。
在第4步和第6步之間,如果發(fā)生異常,Python會將異常的type
,value
和traceback
傳遞給__exit__
方法。
它讓__exit__
方法來決定如何關(guān)閉文件以及是否需要其他步驟。在我們的案例中,我們并沒有注意它們。
那如果我們的文件對象拋出一個異常呢?萬一我們嘗試訪問文件對象的一個不支持的方法。舉個例子:
with File('demo.txt', 'w') as opened_file:
opened_file.undefined_function('Hola!')
我們來列一下,當異常發(fā)生時,with
語句會采取哪些步驟。
type
,value
和traceback
傳遞給__exit__
方法__exit__
方法來處理異常__exit__
返回的是True,那么這個異常就被優(yōu)雅地處理了。__exit__
返回的是True以外的任何東西,那么這個異常將被with
語句拋出。在我們的案例中,__exit__
方法返回的是None
(如果沒有return
語句那么方法會返回None
)。因此,with
語句拋出了那個異常。
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'file' object has no attribute 'undefined_function'
我們嘗試下在__exit__
方法中處理異常:
class File(object):
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, type, value, traceback):
print("Exception has been handled")
self.file_obj.close()
return True
with File('demo.txt', 'w') as opened_file:
opened_file.undefined_function()
# Output: Exception has been handled
我們的__exit__
方法返回了True
,因此沒有異常會被with
語句拋出。
這還不是實現(xiàn)上下文管理器的唯一方式。還有一種方式,我們會在下一節(jié)中一起看看。