這篇“python的with與上下文管理器怎么理解”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“python的with與上下文管理器怎么理解”文章吧。
成都創(chuàng)新互聯(lián)主要從事網(wǎng)站設計、成都網(wǎng)站設計、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務海曙,十余年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:028-86922220
對于系統(tǒng)資源如文件、數(shù)據(jù)庫連接、socket 而言,應用程序打開這些資源并執(zhí)行完業(yè)務邏輯之后,必須做的一件事就是要關閉(斷開)該資源。
比如 Python 程序打開一個文件,往文件中寫內容,寫完之后,就要關閉該文件,否則會出現(xiàn)什么情況呢?極端情況下會出現(xiàn) “Too many open files” 的錯誤,因為系統(tǒng)允許你打開的最大文件數(shù)量是有限的。
同樣,對于數(shù)據(jù)庫,如果連接數(shù)過多而沒有及時關閉的話,就可能會出現(xiàn) “Can not connect to MySQL server Too many connections”,因為數(shù)據(jù)庫連接是一種非常昂貴的資源,不可能無限制的被創(chuàng)建。
來看看如何正確關閉一個文件。
def m1():
f = open("output.txt", "w")
f.write("python之禪")
f.close()
這樣寫有一個潛在的問題,如果在調用 write 的過程中,出現(xiàn)了異常進而導致后續(xù)代碼無法繼續(xù)執(zhí)行,close 方法無法被正常調用,因此資源就會一直被該程序占用者釋放。那么該如何改進代碼呢?
def m2():
f = open("output.txt", "w")
try:
f.write("python之禪")
except IOError:
print("oops error")
finally:
f.close()
改良版本的程序是對可能發(fā)生異常的代碼處進行捕獲,使用 try/finally 語句,該語句表示如果在 try 代碼塊中程序出現(xiàn)了異常,那么后續(xù)代碼不再執(zhí)行,而直接跳轉到 except 代碼塊。不過,最終不管有沒有異常發(fā)生, finally 塊的代碼最終都會被執(zhí)行。因此,即使在 write過程中報錯了,那么最終還是執(zhí)行到 finally 中去 close 文件。
def m3():
with open("output.txt", "r") as f:
f.write("Python之禪")
一種更加簡潔、優(yōu)雅的方式就是用 with 關鍵字。open 的返回值賦值給變量 f,當離開 with 代碼塊的時候,系統(tǒng)會自動調用 f.close() 方法, with 的作用和使用 try/finally 語句是一樣的。那么它的實現(xiàn)原理是什么?在講 with 的原理前要涉及到另外一個概念,就是上下文管理器(Context Manager)。
實現(xiàn)了 __enter__() 和 __exit__() 方法的對象都可稱之為上下文管理器,任何實現(xiàn)了上下文管理器的對象都可以使用 with 關鍵字。顯然,文件(file)對象也實現(xiàn)了上下文管理器。
那么文件對象是如何實現(xiàn)這兩個方法的呢?我們可以模擬實現(xiàn)一個自己的文件類,讓該類實現(xiàn) __enter__() 和 __exit__() 方法。
class File():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
print("entering")
self.f = open(self.filename, self.mode)
return self.f
def __exit__(self, *args):
print("will exit")
self.f.close()
__enter__() 方法返回資源對象,這里就是你將要打開的那個文件對象,__exit__() 方法處理一些清除工作。
因為 File 類實現(xiàn)了上下文管理器,現(xiàn)在就可以使用 with 語句了。
with File('out.txt', 'w') as f:
print("writing")
f.write('hello, python')
這樣,你就無需在顯示地調用 close 方法了。這些有系統(tǒng)去調用。哪怕中間遇到異常 close 方法也會被調用。
Python 還提供了一個 contextmanager 的裝飾器,更進一步簡化了上下文管理器的實現(xiàn)方式。通過 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 f
f.close()
調用
with my_open('out.txt', 'w') as f:
f.write("hello , the simplest context manager")
以上就是關于“python的with與上下文管理器怎么理解”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。