一文帶你搞懂Python上下文管理器
一、什么是上下文管理器
我們在處理文件的時候經(jīng)??吹较旅孢@樣的代碼,它即是上下文管理器:
with open('test.txt', encoding='utf-8') as f:
print(f.readlines())
它的含義是打開當前目錄下的test.txt文件并打印它里面的內(nèi)容,與下面的代碼效果是一樣的:
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', '第三行']
關閉文件
可以看到在我們打印出文件內(nèi)容后,自動執(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內(nèi)置了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())
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!
相關文章
Python 使用dict實現(xiàn)switch的操作
這篇文章主要介紹了Python 使用dict實現(xiàn)switch的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04
python用WxPython庫實現(xiàn)無邊框窗體和透明窗體實現(xiàn)方法詳解
這篇文章主要介紹了python用WxPython庫實現(xiàn)無邊框窗體和透明窗體實現(xiàn)方法詳解,需要的朋友可以參考下2020-02-02
Python使用pydub實現(xiàn)M4A轉MP3轉換器
這篇文章主要介紹了如何使用?wxPython?創(chuàng)建一個圖形用戶界面(GUI)應用程序,能夠將?.m4a?文件轉換為?.mp3?文件,感興趣的可以了解下2024-11-11
Pycharm報錯Non-zero?exit?code?(2)的完美解決方案
最近在使用pycharm安裝或升級模塊時出現(xiàn)了錯誤,下面這篇文章主要給大家介紹了關于Pycharm報錯Non-zero?exit?code?(2)的完美解決方案,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2022-06-06

