跳至內容

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更為可靠。

參考文獻

[編輯]