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

