Python/上下文管理器
外觀
< Python
程序應當對獲取的資源使用後釋放,否則會造成資源泄露。
資源管理基礎
[編輯]常見辦法是open()...close()
這樣的函數:
f = open(filename)
# ...
f.close()
問題是如果代碼塊拋出了異常或者早期return,那麼不會調用資源釋放語句。為此,可以用try...finally
語句:
f = open(filename)
try:
# ...
finally:
f.close()
缺點是手工釋放資源有可能忘記寫了,而且資源釋放語句離資源獲取的距離可能太遠。
自動化的語句with
可以處理File
這樣的上下文管理器類型的資源釋放:
with open(filename) as f:
# ...
實現細節
[編輯]可用於with
的上下文管理器類型(context manager types)必須實現__enter__()
, __exit__()
函數。
__init__()
在創建對象時被調用,__enter__()
在with
語句種被調用返回一個值(如對象、句柄)。
a_cm = A()
with a_cm as a:
...
注意事項
[編輯]上下文,不是作用域
[編輯]with
語句不構成作用域。
生成器
[編輯]生成器持續調用時,可能資源已經釋放了,從而拋出異常。
with open(filename) as f:
lines = (line.rstrip('\n') for line in f)
不是RAII
[編輯]資源獲取即初始化(RAII)不適用於Python這樣的垃圾回收語言。因為即使對象的引用計數為0,也不一定在什麼時候被垃圾回收。所以,用finally更為可靠。
參考文獻
[編輯]外部連結
[編輯]- Get With the Program as Contextmanager
- PyMOTW (Module of the Week): contextlib
- Markus Gattol: Context Manager