Python之上下文管理器

以下文章總結自《head first python》讀書筆記

引子

從python處理一個文件說起,在Python中打開一個文件時,一般的代碼邏輯如下:

file = open('test.txt')
for line in file:
    print(line)
file.close()

以上代碼主要做了3件事:1)打開一個文件;2)處理文件,讀取每一行並打印出來;3)關閉文件

但是對大多數程序員而言,處理文件常推薦使用的是一個with語句。如下:

with open('test.txt') as file:
    for line in file:
        print(line, end='')

明顯的區別是,代碼簡潔了,沒有close調用,這是通過with語句來實現的,只要它的代碼組結束,就會自動調用close。這樣做有效的避免了程序員處理完文件後忘記使用close。尤其如果是寫文件的時候,如果忘記調用close可能會導致數據丟失或破壞。

而with語句就是一個Python內置的上下文管理器。with語句負責管理其代碼組運行的上下文。

創建上下文管理器

首先,前面提到了with是一個內置的上下文管理器(標準庫中也支持創建簡單的上下文管理器,使用contextlib模塊),如果要使用with控制某個外部變量(比如打開文件),一般要創建一個遵循上下文管理協議的類

協議指出,創建的類必須至少定義兩個方法: __enter__和__exit__。這就是協議,如果類遵循這個協議,就可以掛接到with語句。

__enter__完成建立

一個對象用於with語句時,在with語句的代碼組開始之前,解釋器會調用這個對象的__enter__方法。這樣就可以在__enter__中執行必要的建立代碼。

同時enter可以(但不是必須)向with語句返回一個值

__exit__完成清理

一旦with語句的代碼組結束,解釋器就會調用這個對象的__exit__方法。可以在exit方法中編輯對應的清理代碼。

由於with語句的代碼組有可能執行失敗,exit方法必須在發生這種情況時進行處理。

__init__完成初始化

除了上述提到的enter和exit, 還可以根據需要爲類增加其他方法,包括定義自己的__init__。如需要建立此方法,可以將初始化活動和建立活動分離。

定義__init__允許完成額外的對象初始化。init在enter之前運行。

總結一下,

爲了掛接with語句,上下文管理協議需要創建一個提供以下內容的類:

1)__init__方法,來完成初始化(如果需要)

2) __enter__方法, 來完成所有建立工作

3) __exit__方法,來完成所有清理工作。

再回過頭看之前打開文件的例子:

with open('test.txt') as file:
    for line in file:
        print(line, end='')

1)解釋器遇到with語句時,首先調用與open(有一個py文件,定義了一個類,類名爲open,包含init,enter,exit方法)調用關聯的__init__

2)  一旦init執行,解釋器會調用enter來確保調用Open的結果會賦給file變量。

3)with語句結束時,解釋器會調用__exit__來完成清理,會確保打開的文件關閉,然後才繼續。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章