《Python高階程式設計》(二)上下文管理器
阿新 • • 發佈:2019-01-10
上下文管理器
定義
- 上下文管理器是一個包裝任意程式碼塊的物件。上下文管理器保證進入上下文管理器時,每次程式碼執行的一致性;當退出上下文管理器時,相關的資源會被正確回收
- 功能類似於執行try,except和finally關鍵字;被用到最多的就是:作為確保資源被正確清理的一種方式
與裝飾器的對比 :大多數方面上下文管理器與裝飾器的作用等價 - 相似:它們都是包裝其他程式碼的工具。
- 不同:裝飾器包裝用於定義的程式碼塊(函式或類);上下文管理器可以包裝任意格式的程式碼塊
語法
1. with語句
- 使用with語句和內建函式open都可以進入上下文管理器
with open('/path/to/filename', 'r') as my_file:
contents = my_file.read()
- 從本質上講,實際上是with語句對其後的程式碼進行求值,該表示式會返回一個物件,該物件包含兩個特殊方法__enter__和__exit__;__enter__方法返回的結果會被賦給as關鍵字之後的變數。
- 注意:在with後的表示式結果沒有被賦給所謂的變數,只有__enter__的返回值會被賦給該變數
2. enter和exit方法
- with語句的表示式的作用是返回一個遵循特定協議的物件。該物件必須定義一個__enter__和__exit__方法
- 除了傳統的self參量,__enter__不接受任何其他引數
- __exit__方法帶3個位置引數(不包括self):異常型別、異常例項、一個回溯。無異常時三個值均為None
- 上下文管理器必須定義__exit__方法,該方法可以選擇性地處理保證程式碼塊中出現的異常,或者處理其他需要關閉上下文管理器狀態的事情
# 並沒有做什麼工作,僅返回自身和設定其entered變數:進入時True,退出時False
class ContextManager(object):
def __init__(self):
self.entered = False
def __enter__(self):
self.entered = True
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.entered = False
cm = ContextManager()
print cm.entered #False 建立例項
# 使用上下文管理器開啟,entered為True,退出時變為False
with cm:
print cm.entered # True
print cm.entered #False
with ContextManager() as cm:
print cm.entered #True
3. 異常處理
- __exit__方法選擇性地處理包裝程式碼塊中出現的異常,或者處理其他需要關閉上下文管理器狀態的事情。
- 如果沒有異常,__exit__三個引數值都是None,如果接收一個異常,就有義務處理異常。
何時編寫上下文管理器
- 資源清理
示例:開啟PostgreSQL資料庫連線的上下文管理器(未測試)
import psycopg2
class DBConnection(object):
def __init__(self, dbname=None, user=None, password=None, host='localhost'):
self.host = host
self.dbname = dbname
self.user = user
self.password = password
def __enter__(self):
self.connection = psycopg2.connect(
dbname = self.dbname,
host = self.host,
user = self.user,
password = self.password)
return self.connection.cursor()
def __exit__(self, exc_type, exc_instance, exc_traceback):
self.connection.close()
with DBConnection(user='root', dbname='puwell_db') as db:
db.execute('SELECT 1+1')
db.fetchall() #[(2,)]
db.execute('SELECT 1+1') #出錯 InterfaceError:cursor already closed
- 避免重複(還沒完全看懂.待續…)
- 傳播異常
- 終止異常