python中的with上下文管理器
with 語句
with 語句是 Pyhton 提供的一種簡(jiǎn)化語法,確保不管使用過程中是否發(fā)生異常都會(huì)執(zhí)行必要的“清理”操作,釋放資源。
在沒有學(xué)習(xí)with的句法之前,通常我們都是使用try…finally語句,即使是在出現(xiàn)錯(cuò)誤的情況下 也能運(yùn)行某些清理代碼。而今天學(xué)習(xí)的with語句就是對(duì)這些代碼功能的一些簡(jiǎn)單封裝。
with語句通常會(huì)使用在如下的幾個(gè)環(huán)境之中:
- 打開關(guān)閉一個(gè)文件
- 釋放一個(gè)鎖
- 創(chuàng)建一個(gè)臨時(shí)的代碼補(bǔ)丁
- 在特殊環(huán)境下運(yùn)行受保護(hù)的代碼
那么,接下來我們就舉打開關(guān)閉文件的例子說明:
我們先使用file()方法,看看兩者之間有什么不同?
上面的代碼,我們是要打開位于/etc目錄的hosts文件,使用file()方法之后,又手動(dòng)調(diào)用close()關(guān)閉文件。
那么,使用with語句之后,我們可以重寫為:
with的執(zhí)行過程:
在執(zhí)行 with 語句時(shí),首先執(zhí)行 with 后面的 open 代碼
執(zhí)行完代碼后,會(huì)將代碼的結(jié)果通過 as 保存到 hosts 中
然后在下面實(shí)現(xiàn)真正要執(zhí)行的操作
在操作后面,并不需要寫文件的關(guān)閉操作,文件會(huì)在使用完后自動(dòng)關(guān)閉
上下文管理器
任何實(shí)現(xiàn)了 _enter_(self) 和 _exit_(self,exc_type,exc_value,traceback) 方法的對(duì)象都可稱之為上下文管理器,上下文管理器對(duì)象可以使用 with 關(guān)鍵字。顯然,文件(file)對(duì)象也實(shí)現(xiàn)了上下文管理器協(xié)議。
從底層原理的角度來說,with語句的執(zhí)行過程如下:
我們可以模擬實(shí)現(xiàn)一個(gè)自己的文件類,讓該類實(shí)現(xiàn) _enter_() 和 _exit_() 方法。
class File():def __init__(self, filename, mode):self.filename = filenameself.mode = modedef __enter__(self):print("entering")self.f = open(self.filename, self.mode)return self.fdef __exit__(self, *args):print("will exit")self.f.close()注:當(dāng)我們打開文件時(shí),就會(huì)自動(dòng)調(diào)用_enter_,最終會(huì)返回該資源對(duì)象。當(dāng)退出文件時(shí),會(huì)自動(dòng)調(diào)用__exit_方法,把文件關(guān)閉,做一些清理工作。
因?yàn)?File 類實(shí)現(xiàn)了上下文管理器,現(xiàn)在就可以使用 with 語句了。
with File('out.txt', 'w') as f:print("writing")f.write('哈哈哈,你好啊!')contextlib模塊
contextlib模塊是實(shí)現(xiàn)上下文管理的另外一種方式,這個(gè)模塊提供了與上下文管理器一起使用的輔助函數(shù)。它使用的是 contextmanager 裝飾器,通過 yield 將函數(shù)分割成兩部分,yield 之前的語句在\ enter 方法中執(zhí)行,yield 之后的語句在 _exit_ 方法中執(zhí)行。緊跟在 yield 后面的值是函數(shù)的返回值。
from contextlib import contextmanager@contextmanager def my_open(path, mode):f = open(path, mode)yield ff.close()使用:
with my_open('out.txt', 'w') as f:f.write("hello , the simplest context manager")參考文獻(xiàn):
【Python】with及上下文管理器的原理和應(yīng)用
Pythong高級(jí)編程(第二版)
總結(jié)
以上是生活随笔為你收集整理的python中的with上下文管理器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中的魔法属性和方法
- 下一篇: websocket python爬虫_p