一、什么是背景關系管理器
我們在處理檔案的時候經常看到下面這樣的代碼,它即是背景關系管理器:
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()
對比兩種寫法能夠發現,使用with自動執行了f.close()(關閉檔案)的這步操作,能夠少寫一點代碼,
那這樣的背景關系管理器是怎么實作的,下面為你講解,
文章目錄
- 一、什么是背景關系管理器
- 二、如何實作背景關系管理器
- 1. 通過類實作
- 2. 通過contextlib實作
二、如何實作背景關系管理器
1. 通過類實作
如果要實作上面open的背景關系管理器功能,我們可以通過創建一個類,并添加__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())
輸出結果
['第一行\n', '第二行\n', '第三行']
關閉檔案
可以看到在我們列印出檔案內容后,自動執行了關閉檔案的操作,
那__enter__和__exit__的含義是什么,__exit__后面的exc_type, exc_val, exc_tb又是什么意思呢?
1)_enter_
__enter__相對來說好理解的多,當出現with陳述句時,它就會被觸發,有回傳值時,會把回傳值賦值給as宣告的變數,也就是我們上面的as f中的f,
2)_exit_
__exit__是在with執行完成后自動執行的,他后面的引數含義如下:
- exc_type:例外型別
- exc_val:例外原因
- exc_tb:堆疊追蹤資訊
當with中執行的代碼報錯時,除了不繼續執行with包含的代碼外,還會將報錯資訊放入上面的三個引數中,例如下面的代碼:
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讓它不報錯, - 沒有例外資訊時,上面的三個引數值都會為None
2. 通過contextlib實作
Python內置了contextlib這個模塊用于實作背景關系管理器,它是通過生成器yield實作的,這個模塊讓我們不必再創建類和__enter__和__exit__了,
通過contextlib實作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())
新專欄《從0構建自動化測驗平臺》 歡迎訂閱支持!
平臺在線演示地址:http://121.43.43.59/ (帳號:admin 密碼:123456)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/385610.html
標籤:python
