一文帶你搞懂Python上下文管理器
一、什么是上下文管理器
我們?cè)谔幚砦募臅r(shí)候經(jīng)??吹较旅孢@樣的代碼,它即是上下文管理器:
with open('test.txt', encoding='utf-8') as f: print(f.readlines())
它的含義是打開當(dāng)前目錄下的test.txt文件并打印它里面的內(nèi)容,與下面的代碼效果是一樣的:
f = open('test.txt', encoding='utf-8') print(f.readlines()) f.close()
對(duì)比兩種寫法能夠發(fā)現(xiàn),使用with自動(dòng)執(zhí)行了f.close()(關(guān)閉文件)的這步操作,能夠少寫一點(diǎn)代碼。
那這樣的上下文管理器是怎么實(shí)現(xiàn)的,下面為你講解。
二、如何實(shí)現(xiàn)上下文管理器
1. 通過類實(shí)現(xiàn)
如果要實(shí)現(xiàn)上面open
的上下文管理器功能,我們可以通過創(chuàng)建一個(gè)類,并添加__enter__
和__exit__
方法即可,如下面的代碼所示:
class DiyOpen(object): def __init__(self, filename, **kwargs): self.f = open(filename, **kwargs) def __enter__(self): return self.f def __exit__(self, exc_type, exc_val, exc_tb): print('關(guān)閉文件') self.f.close() with DiyOpen('test.txt', encoding='utf-8') as f: print(f.readlines())
輸出結(jié)果
['第一行\(zhòng)n', '第二行\(zhòng)n', '第三行']
關(guān)閉文件
可以看到在我們打印出文件內(nèi)容后,自動(dòng)執(zhí)行了關(guān)閉文件的操作。
那__enter__
和__exit__
的含義是什么,__exit__
后面的exc_type
, exc_val
, exc_tb
又是什么意思呢?
1)_enter_
__enter__
相對(duì)來說好理解的多,當(dāng)出現(xiàn)with語句時(shí),它就會(huì)被觸發(fā),有返回值時(shí),會(huì)把返回值賦值給as聲明的變量,也就是我們上面的as f中的f。
2)_exit_
__exit__
是在with執(zhí)行完成后自動(dòng)執(zhí)行的,他后面的參數(shù)含義如下:
exc_type
:異常類型exc_val
:異常原因exc_tb
:堆棧追蹤信息
當(dāng)with中執(zhí)行的代碼報(bào)錯(cuò)時(shí),除了不繼續(xù)執(zhí)行with包含的代碼外,還會(huì)將報(bào)錯(cuò)信息放入上面的三個(gè)參數(shù)中,例如下面的代碼:
class DiyOpen(object): def __init__(self, filename, **kwargs): self.f = open(filename, **kwargs) def __enter__(self): return self.f def __exit__(self, exc_type, exc_val, exc_tb): print(exc_type) print(exc_val) print(exc_tb) self.f.close() with DiyOpen('test.txt', encoding='utf-8') as f: print(f.no())
輸出結(jié)果
<class 'AttributeError'>
'_io.TextIOWrapper' object has no attribute 'no'
<traceback object at 0x000002A34B834900>
需要注意的是:
- 我們可以手動(dòng)指定__exit__的返回值為True讓它不報(bào)錯(cuò)。
- 沒有異常信息時(shí),上面的三個(gè)參數(shù)值都會(huì)為None
2. 通過contextlib實(shí)現(xiàn)
Python內(nèi)置了contextlib
這個(gè)模塊用于實(shí)現(xiàn)上下文管理器,它是通過生成器yield實(shí)現(xiàn)的,這個(gè)模塊讓我們不必再創(chuàng)建類和__enter__和__exit__了。
通過contextlib
實(shí)現(xiàn)open功能的代碼如下:
from contextlib import contextmanager @contextmanager def diy_open(filename, **kwargs): f = open(filename, **kwargs) # __init__ try: yield f # __enter__ finally: # __exit__ f.close() with diy_open('test.txt', encoding='utf-8') as f: print(f.readlines())
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python?ArcPy實(shí)現(xiàn)批量拼接長時(shí)間序列柵格圖像
這篇文章主要介紹了如何基于Python中ArcPy模塊,對(duì)大量不同時(shí)相的柵格遙感影像按照其成像時(shí)間依次執(zhí)行批量拼接的方法,感興趣的可以了解一下2023-03-03Python實(shí)現(xiàn)的HMacMD5加密算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的HMacMD5加密算法,簡單說明了HMAC-MD5加密算法的概念、原理并結(jié)合實(shí)例形式分析了Python實(shí)現(xiàn)HMAC-MD5加密算法的相關(guān)操作技巧,,末尾還附帶了Java實(shí)現(xiàn)HMAC-MD5加密算法的示例,需要的朋友可以參考下2018-04-04如何使用python-opencv批量生成帶噪點(diǎn)噪線的數(shù)字驗(yàn)證碼
這篇文章主要介紹了如何使用python-opencv批量生成帶噪點(diǎn)噪線的數(shù)字驗(yàn)證碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12詳解pandas庫pd.read_excel操作讀取excel文件參數(shù)整理與實(shí)例
這篇文章主要介紹了pandas庫pd.read_excel操作讀取excel文件參數(shù)整理與實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02Python任意字符串轉(zhuǎn)16, 32, 64進(jìn)制的方法
今天小編就為大家分享一篇Python任意字符串轉(zhuǎn)16, 32, 64進(jìn)制的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-06-06