Python實用程式與with語句上下文 (contextlib)
Python標準庫中的contextlib模組定義了ContextManager類,其物件可以正確管理程式中的資源。Python具有與上下文管理器一起工作的with關鍵字。檔案物件(由內建的open()函式返回)支援ContextManager API。因此,我們經常在處理檔案時使用with關鍵字。
下面的程式碼塊開啟一個檔案並在其中寫入一些資料。操作完成後,檔案將被關閉,否則檔案描述符可能會洩漏,導致檔案損壞。
f = open("file.txt","w")
f.write("hello world")
f.close()但是,使用以下語法使用檔案的上下文管理器功能執行相同的檔案操作。
with open("file.txt","w") as f:
f.write("hello world")
print ("file is closed")如上所述,檔案物件實現了ContextManager。它由with關鍵字啟用。with塊包含要為檔案物件處理的語句。with塊結束後,檔案物件將自動關閉(無需顯式呼叫close()方法)。任何被with塊處理的物件都只在塊內有效,並在其結束時立即被釋放。
ContextManager類有兩個基本方法__enter__()和__exit__()
__enter__() − 當with塊開始時將被呼叫。它表示程式已進入與此物件相關的執行時上下文。
__exit__() − 當with塊結束時被呼叫。它表示程式退出與此物件相關的執行時上下文。
檔案物件也擁有這兩個方法,可以透過以下直譯器會話確認。
>>> f = open("file.txt","w")
>>> f.__enter__()
<_io.TextIOWrapper name = 'file.txt' mode = 'w' encoding = 'cp1252'>
>>> f.write("hello world")
11
>>> f.__exit__()
>>> f.write("hello world")
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
f.write("hello world")
ValueError: I/O operation on closed file.呼叫__exit__()方法時,檔案將被關閉。這就是為什麼在我們嘗試向已關閉的檔案寫入一些資料後出現ValueError的原因。
下面是contextManager更通用的用法。首先,我們定義一個包含__enter__()和__exit__()方法的類,並使用with語句為其物件啟用contextManager。
import contextlib
class WithExample:
def __init__(self):
print ("object initialized")
def __enter__(self):
print ("entered context")
def __exit__(self, *args):
print ("exited context")
with WithExample() as w:
print ('this is a contextlib example')
print ('used by with statement')
print ('end of with block')輸出顯示,with塊開始後,__enter__()方法立即執行。塊內的語句將被處理。當塊結束時,__exit__()方法將自動被呼叫。
object initialized entered context this is a contextlib example used by with statement exited context end of with block
contextlib模組具有@contextmanager裝飾器,藉助它我們可以編寫一個基於生成器的工廠函式來自動支援with語句。使用裝飾器的檔案物件的上下文管理如下所示:
from contextlib import contextmanager
@contextmanager
def openfile(name):
try:
f = open(name, 'w')
yield f
finally:
f.close()
with openfile(file.txt') as f:
f.write('hello world')
print ('file is closed')因此,ContextManager是Python的一個非常有用的特性,可以有效地管理程式中的資源。
資料結構
網路
關係資料庫管理系統 (RDBMS)
作業系統
Java
iOS
HTML
CSS
Android
Python
C程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP