上下文管理器
概念:實現(xiàn)了上下文協(xié)議的對象即為上下文管理器且改。
1. 上下文表達式:with open('test.txt') as f:
2. 上下文管理器:open('test.txt')
3. f 不是上下文管理器验烧,應(yīng)該是資源對象。
上下文管理器的協(xié)議:
__enter__
進入的方法
__exit__
退出的方法
【作用】:一種更加優(yōu)雅的方式又跛,操作(創(chuàng)建/獲取/釋放)資源碍拆,如文件操作、數(shù)據(jù)庫連接;可以以一種更加優(yōu)雅的方式慨蓝,處理異常感混;
with 語句
談及上下文管理器,就不得不提一下with 語句
礼烈,with 語句是 Pyhton 提供的一種簡化語法弧满,適用于對資源進行訪問的場合,確保不管使用過程中是否發(fā)生異常都會執(zhí)行必要的“清理”操作此熬,釋放資源庭呜,with 語句主要是為了簡化代碼操作。
語法如下:
with context as var:
statements(語句)
【知識拓展】:線程中的鎖其實也實現(xiàn)了上下文管理協(xié)議:
import threading
withthreading.Lock():
# 關(guān)鍵部分
statements
# 關(guān)鍵部分結(jié)束
- with:當(dāng)文件操作執(zhí)行完成后犀忱, with語句會自動調(diào)用上下文管理器里的關(guān)閉語句來關(guān)閉文件資源募谎。
- with 語句的實現(xiàn)原理建立在上下文管理器之上
【注釋】Python 提供了 with 語法用于簡化資源操作的后續(xù)清除操作,是try / finally
的替代方法阴汇。Python 還提供了一個 contextmanager 裝飾器数冬,更進一步簡化上下管理器的實現(xiàn)方式。
【耿直插播】contextlib模塊
的contextmanager裝飾器
可以更方便的實現(xiàn)上下文管理器搀庶。(使用裝飾器在一定程度上也簡化了代碼)
任何能夠被yield關(guān)鍵詞分割成兩部分的函數(shù)拐纱,都能夠通過裝飾器裝飾的上下文管理器來實現(xiàn)疯淫。任何在yield之前的內(nèi)容都可以看做在__enter__
中的代碼執(zhí)行前的操作,而任何yield之后的操作都可以放在__exit__
函數(shù)中戳玫。
下面講講關(guān)于上下文管理器的協(xié)議的用法
__enter__
方法會在執(zhí)行 with 后面的語句時執(zhí)行熙掺,一般用來處理操作前的內(nèi)容。比如一些創(chuàng)建對象咕宿,初始化等币绩;
__exit__
方法會在 with 內(nèi)的代碼執(zhí)行完畢后執(zhí)行,一般用來處理一些善后收尾工作府阀,比如文件的關(guān)閉缆镣,數(shù)據(jù)庫的關(guān)閉等。
__exit__
方法的參數(shù)
__exit__
方法中有三個參數(shù)试浙,用來接收處理異常董瞻,如果代碼在運行時發(fā)生異常,異常會被保存到這里田巴。 __exit__
函數(shù)就能夠拿到關(guān)于異常的所有信息(異常類型钠糊,異常值以及異常追蹤信息),這些信息將幫助異常處理操作壹哺。
exc_type
: 【異常類型】exc_val
: 【異常值】exc_tb
: 【異吵椋回溯追蹤】
關(guān)于上下文管理器的用法,舉個實際的例子來看看:
import sys
class lookingGlass:
def __enter__(self):
self.original_write = sys.stdout.write
sys.stdout.write = self.reverse_write
return "ASDFGHJKL"
def reverse_write(self, text):
self.original_write(text[::-1])
def __exit__(self, exc_type, exc_val, exc_tb):
"""
:param exc_type: 異常的類型
:param exc_val: 異常實例 except ZeroDivisionError as data
:param exc_tb: traceback對象
:return:
"""
sys.stdout.write = self.original_write
return True
# 如果返會True 則代表已正確處理異常管宵;如果返會TRUE以外的其他值截珍,則代表異常未處理,異常會層層上拋
with lookingGlass() as what:
print("ABC$$$$HJK")
print(what)
import contextlib
@contextlib.contextmanager
def looking_glass():
original_write = sys.stdout.write
def reverse_write(text):
# original_write(text[1:10:-1])
original_write(text[::-1])
sys.stdout.write = reverse_write
yield 'AAA¥¥¥SSS'
# 以yield為分界點箩朴, yield之后的代碼相當(dāng)于__exit__中的代碼岗喉;yield之前的代碼,相當(dāng)于__enter__中的代碼
# yield 的值相當(dāng)于__exit__中的返回值炸庞;
sys.stdout.write = reverse_write
print('-------$$$$------')
with looking_glass() as ABC:
print('Zurich')
print(ABC)
下面钱床,我們來分析一下實現(xiàn)過程。