Python中的上下文管理器和with語(yǔ)句的使用
Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于規(guī)定某個(gè)對(duì)象的使用范圍。本文是針對(duì)于該功能的思考總結(jié)。
為什么需要上下文管理器?
首先,需要思索下為什么需要引入上下文管理器。
在正常情況下,管理各種系統(tǒng)資源(如文件)、數(shù)據(jù)庫(kù)連接時(shí),通常是先打開這些資源,執(zhí)行完相應(yīng)的業(yè)務(wù)邏輯,最后關(guān)閉資源。
舉兩個(gè)例子:
1.使用Python打開一個(gè)文件寫入內(nèi)容,之后需要關(guān)閉這個(gè)文件。如果不正常關(guān)閉的話可能會(huì)在文件操作時(shí)出現(xiàn)異常,因?yàn)橄到y(tǒng)允許你打開的文件的最大數(shù)是有限的。
2.在數(shù)據(jù)庫(kù)連接時(shí)也是存在類似問題,數(shù)據(jù)庫(kù)的連接算是一種比較昂貴的資源,若連接過多而沒有及時(shí)關(guān)閉的話,就可能出現(xiàn)不能繼續(xù)連接的異常錯(cuò)誤。
但是,很多程序員經(jīng)常會(huì)忘記關(guān)閉文件,或者關(guān)閉數(shù)據(jù)庫(kù)的連接。這時(shí)候就引入了上下文管理器,它可以在你不需要該對(duì)象的時(shí)候,自動(dòng)關(guān)閉它。
上下文管理器怎么使用?
上下文管理器的語(yǔ)法是:with...as...
實(shí)例:文件操作
print "不使用上下文管理器" print "*" * 30 f = open('file.py', 'w') print f.closed f.write("# Hello World") f.close() print f.closed print "\n使用上下文管理器" print "*" * 30 with open("file.py", 'w') as f: print f.closed f.write('# Hello Python') print f.closed
這里通過.closed比較,我們可以看到上下文管理器可以自動(dòng)關(guān)閉文件,對(duì)于上下文管理器而言,有隸屬于它的程序塊,當(dāng)隸屬于它的程序塊執(zhí)行結(jié)束的時(shí)候(判斷縮進(jìn)),上下文管理器將自動(dòng)關(guān)閉文件。
上述實(shí)例,也可以使用try...except...來實(shí)現(xiàn),同樣可以很直觀的看到使用with...as...語(yǔ)句之后,代碼確實(shí)相對(duì)更加簡(jiǎn)潔。
上下文管理實(shí)現(xiàn)機(jī)制
因?yàn)槲募?duì)象是Python的內(nèi)置對(duì)象,內(nèi)置了上下文管理的特殊方法,所以它可以使用with語(yǔ)句。在Python中,任何對(duì)象,只要實(shí)現(xiàn)了上下文管理,就可以使用with語(yǔ)句,實(shí)現(xiàn)上下文管理需要通過__enter__和__exit__這兩個(gè)方法來實(shí)現(xiàn)。
關(guān)于這兩個(gè)方法:
- enter(self):進(jìn)入該對(duì)象時(shí)調(diào)用此方法,返回值將放入with...as...語(yǔ)句中的as說明的變量中
- exit(self, type, value, tb):離開上下文管理器時(shí)調(diào)用該方法,如果有異常出現(xiàn),返回False,type、value和tb將分別表示異常的類型、值和追蹤信息,傳遞出上下文顯示;如果沒有異常,則三個(gè)變量的值均為None。
with 上下文管理器:
語(yǔ)法體
當(dāng)with語(yǔ)句遇到上下文管理器時(shí),就會(huì)在執(zhí)行語(yǔ)法體之前,先執(zhí)行__enter__方法,然后再執(zhí)行語(yǔ)法體,執(zhí)行完語(yǔ)法體之后,執(zhí)行__exit__方法。
上下文管理器實(shí)現(xiàn)
使用Python2.7X實(shí)現(xiàn)一個(gè)上下文管理器:
class Context(object): def __init__(self): print "實(shí)例化一個(gè)對(duì)象" def __enter__(self): print "獲取該對(duì)象" def __exit__(self, exc_type, exc_val, exc_tb): print "退出該對(duì)象" temp = Context() with temp: print "執(zhí)行體"
這樣,__enter__方法和__exit__方法的調(diào)用過程就很明晰。
contextLib
在contextlib中,提供了contextmanager裝飾器,通過yield返回函數(shù)將函數(shù)分隔為兩部分,yield之前的語(yǔ)句在__enter__中執(zhí)行,yield之后的語(yǔ)句在__exit__中執(zhí)行,簡(jiǎn)化了上下文管理器的實(shí)現(xiàn)方式:
總結(jié):通過上下文管理器,我們可以更好的控制對(duì)象在不同區(qū)間的特性,并且可以使用with語(yǔ)句替代try...except方法,使得代碼更加的簡(jiǎn)潔,主要的使用場(chǎng)景是訪問資源,可以保證不管過程中是否發(fā)生錯(cuò)誤或者異常都會(huì)執(zhí)行相應(yīng)的清理操作,釋放出訪問的資源。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python 發(fā)送SMTP郵件的簡(jiǎn)單教程
SMTP(Simple Mail Transfer Protocol)簡(jiǎn)單郵件傳輸協(xié)議,Python內(nèi)置對(duì)SMTP的支持,可以發(fā)送純文本文件,HTML郵件以及附帶文件。本文講解如何使用python發(fā)送郵件2021-06-06Python數(shù)據(jù)可視化實(shí)現(xiàn)正態(tài)分布(高斯分布)
這篇文章主要介紹了Python數(shù)據(jù)可視化實(shí)現(xiàn)正態(tài)分布(高斯分布),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Python使用Flask Migrate模塊遷移數(shù)據(jù)庫(kù)
Flask-Migrate是一個(gè)為Flask應(yīng)用處理SQLAlchemy數(shù)據(jù)庫(kù)遷移的擴(kuò)展,使得可以通過Flask的命令行接口或者Flask-Scripts對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作2022-07-07django實(shí)現(xiàn)悲觀鎖樂觀鎖的項(xiàng)目實(shí)踐
在Django中,我們可以通過實(shí)現(xiàn)悲觀鎖和樂觀鎖來保證數(shù)據(jù)的安全性,本文就來介紹一下django實(shí)現(xiàn)悲觀鎖樂觀鎖的項(xiàng)目實(shí)踐,感興趣的可以了解一下2023-08-08python誤差棒圖errorbar()函數(shù)實(shí)例解析
這篇文章主要介紹了python誤差棒圖errorbar()函數(shù)實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02Python+matplotlib實(shí)現(xiàn)簡(jiǎn)單曲線的繪制
Matplotlib是Python的繪圖庫(kù),它能讓使用者很輕松地將數(shù)據(jù)圖形化,并且提供多樣化的輸出格式。本文將利用matplotlib繪制簡(jiǎn)單的曲線圖,感興趣的朋友可以學(xué)習(xí)一下2022-04-04