python的上下文管理器,是爲了節省是打開某資源後,不管出現什麼異常都要關閉的代碼try ... finally ...
, 能夠簡寫爲with .. as ..
python
上下文管理器的協議包含__enter__
和__exit__
兩個方法,在with語句開始運行時,會調用__enter__
方法。with語句結束後,會調用__exit__
方法。測試
建立類,實現__enter__
和__exit__
方法。若是with代碼塊中拋出異常,exc_type
是異常類型類, exc_val
是異常值,exc_tb
是錯誤棧對象code
class LookingGlass: def __enter__(self): print('start') return 'running' def __exit__(self, exc_type, exc_val, exc_tb): print('end') def test_1(): with LookingGlass() as what: print(what) Output: start running end
實現一個類感受挺麻煩。利用contextlib.contextmanager裝飾方法,咱們能夠沒必要顯式實現協議,利用yield,來分割。yield以前能夠看做是__enter__
方法的內容,yield以後能夠當作是__exit__
方法的內容。yield生成的就是給as後的變量賦值。對象
from contextlib import contextmanager @contextmanager def context(): print('start') # __enter__ try: yield 'running' # as ... except Exception as e: raise e # 再次拋出異常 finally: print('end') # __exit__ def test_2(): with context() as what: print(what) # raise 測試 Output: start running end
注意: yield語句必定要寫在try/except/finally中,由於@contextmanager不會處理with代碼塊中出現的異常,會在yield中拋出,若是不try/except,程序會停止,__exit__方法都不會執行(即看不到end輸出)!資源