您好,登錄后才能下訂單哦!
實(shí)際上,Python 提供了 with 語句來管理資源關(guān)閉。比如可以把打開的文件放在 with 語句中,這樣 with 語句就會幫我們自動關(guān)閉文件。
with 語句的語法格式如下:
with context expression [as target(s)]: with 代碼塊
在上面的語法格式中,context_expression 用于創(chuàng)建可自動關(guān)閉的資源。
例如,程序使用 with 語句來讀取文件:
import codecs # 使用with語句打開文件,該語句會負(fù)責(zé)關(guān)閉文件 with codecs.open("readlines_test.py", 'r', 'utf-8', buffering=True) as f: for line in f: print(line, end='')
程序也可以使用 with 語句來處理通過 fileinput.input 合并的多個文件,例如如下程序:
import fileinput # 使用with語句打開文件,該語句會負(fù)責(zé)關(guān)閉文件 with fileinput.input(files=('test.txt', 'info.txt')) as f: for line in f: print(line, end='')
上面兩個程序都使用了 with 語句來管理資源,因此它們都不需要顯式關(guān)閉文件。
那么,with 語句的實(shí)現(xiàn)原理是什么?其實(shí)很簡單,使用 with 語句管理的資源必須是一個實(shí)現(xiàn)上下文管理協(xié)議(context manage protocol)的類,這個類的對象可被稱為上下文管理器。要實(shí)現(xiàn)上下文管理協(xié)議,必須實(shí)現(xiàn)如下兩個方法:
通過上面的介紹不難發(fā)現(xiàn),只要一個類實(shí)現(xiàn)了 __enter__() 和 __exit__(exc_type, exc_value, exc_traceback) 方法,程序就可以使用 with 語句來管理它;通過 __exit__() 方法的參數(shù),即可判斷出 with 代碼塊執(zhí)行時是否遇到了異常。
換而言之,上面程序所用的文件對象、FileInput 對象,其實(shí)都實(shí)現(xiàn)了這兩個方法,因此它們都可以接受 with 語句的管理。
下面我們自定義一個實(shí)現(xiàn)上下文管理協(xié)議的類,并使用 with 語句來管理它:
class FkResource: def __init__(self, tag): self.tag = tag print('構(gòu)造器,初始化資源: %s' % tag) # 定義__enter__方法,with體之前的執(zhí)行的方法 def __enter__(self): print('[__enter__ %s]: ' % self.tag) # 該返回值將作為as子句中變量的值 return 'fkit' # 可以返回任意類型的值 # 定義__exit__方法,with體之后的執(zhí)行的方法 def __exit__(self, exc_type, exc_value, exc_traceback): print('[__exit__ %s]: ' % self.tag) # exc_traceback為None,代表沒有異常 if exc_traceback is None: print('沒有異常時關(guān)閉資源') else: print('遇到異常時關(guān)閉資源') return False # 可以省略,默認(rèn)返回None也被看做是False with FkResource('孫悟空') as dr: print(dr) print('[with代碼塊] 沒有異常') print('------------------------------') with FkResource('白骨精'): print('[with代碼塊] 異常之前的代碼') raise Exception print('[with代碼塊] ~~~~~~~~異常之后的代碼')
上面程序定義了一個 FkResource 類,該類定義了 __enter__() 和 __exit__() 兩個方法,因此該類的對象可以被 with 語句管理:
程序兩次使用 with 語句管理 FkResource 對象。第一次,with 代碼塊沒有出現(xiàn)異常。第二次,with 代碼塊出現(xiàn)了異常。大家可以看到,使用 with 語句兩次對 FkResource 的管理略有差異(主要是在 __exit()__ 方法中略有差異)。
運(yùn)行上面的程序,可以看到如下輸出結(jié)果:
構(gòu)造器,初始化資源: 孫悟空 [__enter__ 孫悟空]: fkit [with代碼塊] 沒有異常 [__exit__ 孫悟空]: 沒有異常時關(guān)閉資源 ------------------------------ 構(gòu)造器,初始化資源: 白骨精 [__enter__ 白骨精]: [with代碼塊] 異常之前的代碼 [__exit__ 白骨精]: 遇到異常時關(guān)閉資源 Traceback (most recent call last): File "C:\Users\mengma\Desktop\1.py", line 26, in <module> raise Exception Exception
從上面的輸出結(jié)果來看,使用 with 語句管理資源,程序總可以在進(jìn)入 with 代碼塊之前自動執(zhí)行 __enter__() 方法,無論 with 代碼塊是否有異常,這個部分都是一樣的,而且 __enter__() 方法的返回值被賦值給了 as 子句后的變量,如上面的 ① 號輸出信息所示。
對于 with 代碼塊有異常和無異常這兩種情況,此時主要通過 exit() 方法的參數(shù)進(jìn)行判斷,程序可針對 with 代碼塊是否有異常分別進(jìn)行處理,如程序中代碼所示。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。