一文帶你搞懂Python上下文管理器
一、什么是上下文管理器
我們?cè)谔幚砦募臅r(shí)候經(jīng)常看到下面這樣的代碼,它即是上下文管理器:
with open('test.txt', encoding='utf-8') as f:
print(f.readlines())
它的含義是打開(kāi)當(dāng)前目錄下的test.txt文件并打印它里面的內(nèi)容,與下面的代碼效果是一樣的:
f = open('test.txt', encoding='utf-8')
print(f.readlines())
f.close()
對(duì)比兩種寫(xiě)法能夠發(fā)現(xiàn),使用with自動(dòng)執(zhí)行了f.close()(關(guān)閉文件)的這步操作,能夠少寫(xiě)一點(diǎn)代碼。
那這樣的上下文管理器是怎么實(shí)現(xiàn)的,下面為你講解。
二、如何實(shí)現(xiàn)上下文管理器
1. 通過(guò)類(lèi)實(shí)現(xiàn)
如果要實(shí)現(xiàn)上面open的上下文管理器功能,我們可以通過(guò)創(chuàng)建一個(gè)類(lèi),并添加__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ì)來(lái)說(shuō)好理解的多,當(dāng)出現(xiàn)with語(yǔ)句時(shí),它就會(huì)被觸發(fā),有返回值時(shí),會(huì)把返回值賦值給as聲明的變量,也就是我們上面的as f中的f。
2)_exit_
__exit__是在with執(zhí)行完成后自動(dòng)執(zhí)行的,他后面的參數(shù)含義如下:
exc_type:異常類(lèi)型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__的返回值為T(mén)rue讓它不報(bào)錯(cuò)。
- 沒(méi)有異常信息時(shí),上面的三個(gè)參數(shù)值都會(huì)為None
2. 通過(guò)contextlib實(shí)現(xiàn)
Python內(nèi)置了contextlib這個(gè)模塊用于實(shí)現(xiàn)上下文管理器,它是通過(guò)生成器yield實(shí)現(xiàn)的,這個(gè)模塊讓我們不必再創(chuàng)建類(lèi)和__enter__和__exit__了。
通過(guò)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é)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python?ArcPy實(shí)現(xiàn)批量拼接長(zhǎng)時(shí)間序列柵格圖像
這篇文章主要介紹了如何基于Python中ArcPy模塊,對(duì)大量不同時(shí)相的柵格遙感影像按照其成像時(shí)間依次執(zhí)行批量拼接的方法,感興趣的可以了解一下2023-03-03
Python實(shí)現(xiàn)的HMacMD5加密算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的HMacMD5加密算法,簡(jiǎn)單說(shuō)明了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)噪線(xiàn)的數(shù)字驗(yàn)證碼
這篇文章主要介紹了如何使用python-opencv批量生成帶噪點(diǎn)噪線(xiàn)的數(shù)字驗(yàn)證碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Python使用PyYAML庫(kù)讀寫(xiě)yaml文件的方法
這篇文章主要介紹了Python使用PyYAML庫(kù)讀寫(xiě)yaml文件的方法,包括YAML基本概念介紹及YAML語(yǔ)法知識(shí),結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04
詳解pandas庫(kù)pd.read_excel操作讀取excel文件參數(shù)整理與實(shí)例
這篇文章主要介紹了pandas庫(kù)pd.read_excel操作讀取excel文件參數(shù)整理與實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
Python任意字符串轉(zhuǎn)16, 32, 64進(jìn)制的方法
今天小編就為大家分享一篇Python任意字符串轉(zhuǎn)16, 32, 64進(jìn)制的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06

