Python中with上下文管理協(xié)議的作用及用法
1、簡(jiǎn)介
with是從Python2.5引入的一個(gè)新的語(yǔ)法,它是一種上下文管理協(xié)議,目的在于從流程圖中把 try,except 和finally 關(guān)鍵字和資源分配釋放相關(guān)代碼統(tǒng)統(tǒng)去掉,簡(jiǎn)化try…except…finlally
的處理流程。
那我們先理解一下try…except…finally語(yǔ)句是干啥的。實(shí)際上,try…except語(yǔ)句和try…finally語(yǔ)句是兩種語(yǔ)句,用于不同的場(chǎng)景。但是當(dāng)二者結(jié)合在一起時(shí),可以“實(shí)現(xiàn)穩(wěn)定性和靈活性更好的設(shè)計(jì)”。
2、try… except語(yǔ)句
用于處理程序執(zhí)行過(guò)程中的異常情況,比如語(yǔ)法錯(cuò)誤、從未定義變量上取值等等,也就是一些python程序本身引發(fā)的異常、報(bào)錯(cuò)。而try… except語(yǔ)句就是為了防止一些報(bào)錯(cuò)影響你的程序繼續(xù)運(yùn)行,就用try語(yǔ)句把它們抓出來(lái)(捕獲)。
(1)try…except的標(biāo)準(zhǔn)格式
try: ? ? ? ## normal block ? except A: ? ? ? ## exc A block ? except: ? ? ? ## exc other block ? else: ?
(2)程序執(zhí)行流程
–>執(zhí)行normal block
–>發(fā)現(xiàn)有A錯(cuò)誤,執(zhí)行 exc A block(即處理異常)
–>結(jié)束
如果沒(méi)有A錯(cuò)誤呢?
–>執(zhí)行normal block
–>發(fā)現(xiàn)B錯(cuò)誤,開(kāi)始尋找匹配B的異常處理方法,發(fā)現(xiàn)A,跳過(guò),發(fā)現(xiàn)except others(即except:),執(zhí)行exc other block
–>結(jié)束
如果沒(méi)有錯(cuò)誤呢?
–>執(zhí)行normal block
–>全程沒(méi)有錯(cuò)誤,跳入else 執(zhí)行noError block
–>結(jié)束
(3)異常分類(lèi)
except
后面還能跟表達(dá)式的! 所謂的表達(dá)式,就是錯(cuò)誤的定義。也就是說(shuō),我們可以捕捉一些我們想要捕捉的異常。而不是什么異常都報(bào)出來(lái)。
異常分兩類(lèi):
- python標(biāo)準(zhǔn)異常
- 自定義異常
(a)Python標(biāo)準(zhǔn)異常
Python標(biāo)準(zhǔn)異常包括NameError
(未聲明/初始化對(duì)象,沒(méi)有屬性),MemoryError
內(nèi)存溢出錯(cuò)誤等錯(cuò)誤,
詳細(xì)python標(biāo)準(zhǔn)異常詳見(jiàn):
異常名稱(chēng) | 描述 |
---|---|
BaseException | 所有異常的基類(lèi) |
SystemExit | 解釋器請(qǐng)求退出 |
KeyboardInterrupt | 用戶(hù)中斷執(zhí)行(通常是輸入^C) |
Exception | 常規(guī)錯(cuò)誤的基類(lèi) |
StopIteration | 迭代器沒(méi)有更多的值 |
GeneratorExit | 生成器(generator)發(fā)生異常來(lái)通知退出 |
StandardError | 所有的內(nèi)建標(biāo)準(zhǔn)異常的基類(lèi) |
ArithmeticError | 所有數(shù)值計(jì)算錯(cuò)誤的基類(lèi) |
FloatingPointError | 浮點(diǎn)計(jì)算錯(cuò)誤 |
OverflowError | 數(shù)值運(yùn)算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有數(shù)據(jù)類(lèi)型) |
AssertionError | 斷言語(yǔ)句失敗 |
AttributeError | 對(duì)象沒(méi)有這個(gè)屬性 |
EOFError | 沒(méi)有內(nèi)建輸入,到達(dá)EOF 標(biāo)記 |
EnvironmentError | 操作系統(tǒng)錯(cuò)誤的基類(lèi) |
IOError | 輸入/輸出操作失敗 |
OSError | 操作系統(tǒng)錯(cuò)誤 |
WindowsError | 系統(tǒng)調(diào)用失敗 |
ImportError | 導(dǎo)入模塊/對(duì)象失敗 |
LookupError | 無(wú)效數(shù)據(jù)查詢(xún)的基類(lèi) |
IndexError | 序列中沒(méi)有此索引(index) |
KeyError | 映射中沒(méi)有這個(gè)鍵 |
MemoryError | 內(nèi)存溢出錯(cuò)誤(對(duì)于Python 解釋器不是致命的) |
NameError | 未聲明/初始化對(duì)象 (沒(méi)有屬性) |
UnboundLocalError | 訪(fǎng)問(wèn)未初始化的本地變量 |
ReferenceError | 弱引用(Weak reference)試圖訪(fǎng)問(wèn)已經(jīng)垃圾回收了的對(duì)象 |
RuntimeError | 一般的運(yùn)行時(shí)錯(cuò)誤 |
NotImplementedError | 尚未實(shí)現(xiàn)的方法 |
SyntaxError | Python 語(yǔ)法錯(cuò)誤 |
IndentationError | 縮進(jìn)錯(cuò)誤 |
TabError | Tab 和空格混用 |
SystemError | 一般的解釋器系統(tǒng)錯(cuò)誤 |
TypeError | 對(duì)類(lèi)型無(wú)效的操作 |
ValueError | 傳入無(wú)效的參數(shù) |
UnicodeError | Unicode 相關(guān)的錯(cuò)誤 |
UnicodeDecodeError | Unicode 解碼時(shí)的錯(cuò)誤 |
UnicodeEncodeError | Unicode 編碼時(shí)錯(cuò)誤 |
UnicodeTranslateError | Unicode 轉(zhuǎn)換時(shí)錯(cuò)誤 |
Warning | 警告的基類(lèi) |
DeprecationWarning | 關(guān)于被棄用的特征的警告 |
FutureWarning | 關(guān)于構(gòu)造將來(lái)語(yǔ)義會(huì)有改變的警告 |
OverflowWarning | 舊的關(guān)于自動(dòng)提升為長(zhǎng)整型(long)的警告 |
PendingDeprecationWarning | 關(guān)于特性將會(huì)被廢棄的警告 |
RuntimeWarning | 可疑的運(yùn)行時(shí)行為(runtime behavior)的警告 |
SyntaxWarning | 可疑的語(yǔ)法的警告 |
UserWarning | 用戶(hù)代碼生成的警告 |
例:
? try: ? ? ? ? a = 1 / 2 ? ? ? ? print(a) ? ? ? ? print(m) ?# 此處拋出python標(biāo)準(zhǔn)異常 ? ? ? ? b = 1 / 0 ?# 此后的語(yǔ)句不執(zhí)行 ? ? ? ? print(b) ? ? ? ? c = 2 / 1 ? ? ? ? print(c) ? ? except NameError: ? ? ? ? print("Ops!!") ? ? except ZeroDivisionError: ? ? ? ? print("Wrong math!!") ? ? except: ? ? ? ? print("Error")
輸出:
3、try…finallly語(yǔ)句
try…finallly
語(yǔ)句用于無(wú)論執(zhí)行過(guò)程中有沒(méi)有異常,都要執(zhí)行清場(chǎng)工作。
格式:
try: ? ? ? execution block ?##正常執(zhí)行模塊 ? except A: ? ? ? exc A block ##發(fā)生A錯(cuò)誤時(shí)執(zhí)行 ? except B: ? ? ? exc B block ##發(fā)生B錯(cuò)誤時(shí)執(zhí)行 ? except: ? ? ? other block ##發(fā)生除了A,B錯(cuò)誤以外的其他錯(cuò)誤時(shí)執(zhí)行 ? else: ? ? ? if no exception, jump to here ##沒(méi)有錯(cuò)誤時(shí)執(zhí)行 ? finally: ? final block ?##總是執(zhí)行 ?
tips: 注意順序不能亂,否則會(huì)有語(yǔ)法錯(cuò)誤。如果用else就必須有except,否則會(huì)有語(yǔ)法錯(cuò)誤。
例:
?try: ? ? ? ? a = 1 / 2 ? ? ? ? print(a) ? ? ? ? print(m) ?# 拋出NameError異常 ? ? ? ? b = 1 / 0 ? ? ? ? print(b) ? ? ? ? c = 2 / 1 ? ? ? ? print(c) ? ? except NameError: ? ? ? ? print("Ops!!") ?# 捕獲到異常 ? ? except ZeroDivisionError: ? ? ? ? print("Wrong math!!") ? ? except: ? ? ? ? print("Error") ? ? else: ? ? ? ? print("No error! yeah!") ? ? finally: ?# 是否異常都執(zhí)行該代碼塊 ? ? ? ? print("finally!")
輸出:
4、with…as語(yǔ)句
(1)With語(yǔ)句的基本語(yǔ)法
with通過(guò)__enter__方法初始化,然后在__exit__中做善后以及處理異常。其中__enter__()方法在語(yǔ)句體(with語(yǔ)句包裹起來(lái)的代碼塊)執(zhí)行之前進(jìn)入運(yùn)行,__exit__()方法在語(yǔ)句體執(zhí)行完畢退出后運(yùn)行。
with 語(yǔ)句適用于對(duì)資源進(jìn)行訪(fǎng)問(wèn)的場(chǎng)合,確保不管使用過(guò)程中是否發(fā)生異常都會(huì)執(zhí)行必要的“清理”操作,釋放資源,比如文件使用后自動(dòng)關(guān)閉、線(xiàn)程中鎖的自動(dòng)獲取和釋放等。
With語(yǔ)句的基本語(yǔ)法格式:
with expression [as target]: with-block ?
expression
:是一個(gè)需要執(zhí)行的表達(dá)式;target
:是一個(gè)變量或者元組,存儲(chǔ)的是expression
表達(dá)式執(zhí)行返回的結(jié)果,可選參數(shù)。
(2)with語(yǔ)句原理
- 上下文管理協(xié)議(Context Management Protocol):包含方法 __enter__()和__exit__(),支持該協(xié)議的對(duì)象要實(shí)現(xiàn)這兩個(gè)方法。
- 上下文管理器(Context Manager):支持上下文管理協(xié)議的對(duì)象,這種對(duì)象實(shí)現(xiàn)了__enter__()和__exit__()方法。上下文管理器定義執(zhí)行with語(yǔ)句時(shí)要建立的運(yùn)行時(shí)上下文,負(fù)責(zé)執(zhí)行with語(yǔ)句塊上下文中的進(jìn)入與退出操作。通常使用with語(yǔ)句調(diào)用上下文管理器,也可以通過(guò)直接調(diào)用其方法來(lái)使用。
例:執(zhí)行過(guò)程
with EXPR as VAR: ? ? BLOCK
(1)執(zhí)行EXPR,生成上下文管理器context_manager
;
(2)獲取上下文管理器的__exit()__方法,并保存起來(lái)用于之后的調(diào)用;
(3)調(diào)用上下文管理器的__enter__()方法;如果使用了as子句,則將__enter__()方法的返回值賦值給as子句中的VAR;
(4)執(zhí)行BLOCK中的表達(dá)式;
(5)不管是否執(zhí)行過(guò)程中是否發(fā)生了異常,執(zhí)行上下文管理器的__exit__()
方法,__exit__()方法負(fù)責(zé)執(zhí)行“清理”工作,如釋放資源等。如果執(zhí)行過(guò)程中沒(méi)有出現(xiàn)異常,或者語(yǔ)句體中執(zhí)行了語(yǔ)句break/continue/return,則以None作為參數(shù)調(diào)用__exit__(None, None, None);如果執(zhí)行過(guò)程中出現(xiàn)異常,則使用sys.exc_info得到的異常信息為參數(shù)調(diào)用__exit__
(exc_type, exc_value, exc_traceback);
(6)出現(xiàn)異常時(shí),如果__exit__
(type, value, traceback)返回False,則會(huì)重新拋出異常,讓with之外的語(yǔ)句邏輯來(lái)處理異常,這也是通用做法;如果返回True,則忽略異常,不再對(duì)異常進(jìn)行處理。
這個(gè)和try finally函數(shù)有什么關(guān)系呢?其實(shí),這樣的過(guò)程等價(jià)于:
try:
執(zhí)行 __enter__的內(nèi)容
執(zhí)行 with_block.
finally:
執(zhí)行 __exit__內(nèi)容
例:
class Sample(object): ? ? ? def __init__(self): ? ? ? ? print("__init__") ? ? ? def __enter__(self): ? ? ? ? print("__enter__") ? ? ? def __exit__(self, types, values, trace): ? ? ? ? print("type:", types) ? ? ? ? print("value:", values) ? ? ? ? print("trace:", trace) ? ? def get_sample(): ? ? return Sample() ? ? if __name__ == '__main__': ? ? # get_data() ? ? with get_sample() as sample: ? ? ? ? print("Sample:", sample)
輸出:
到此這篇關(guān)于Python中with上下文管理協(xié)議的作用及用法的文章就介紹到這了,更多相關(guān)Python中with用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python導(dǎo)入導(dǎo)出redis數(shù)據(jù)的實(shí)現(xiàn)
本文主要介紹了python導(dǎo)入導(dǎo)出redis數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02基于Python實(shí)現(xiàn)自動(dòng)化文檔整理工具
一個(gè)人可能會(huì)在計(jì)算機(jī)上存儲(chǔ)大量的照片、視頻和文檔文件,這些文件可能散落在不同的文件夾中,難以管理和查找。所以本文就來(lái)用Python制作一個(gè)自動(dòng)化文檔整理工具吧2023-04-04Python 26進(jìn)制計(jì)算實(shí)現(xiàn)方法
這篇文章主要介紹了Python 26進(jìn)制計(jì)算實(shí)現(xiàn)方法,涉及Python字符串與數(shù)值計(jì)算的相關(guān)操作技巧,需要的朋友可以參考下2015-05-05Python實(shí)現(xiàn)獲取網(wǎng)頁(yè)內(nèi)容及自動(dòng)填表單與登錄功能
這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)模擬瀏覽器啟動(dòng),獲取網(wǎng)頁(yè)內(nèi)容、自動(dòng)填表單、自動(dòng)登錄、自動(dòng)過(guò)驗(yàn)證碼等功能,需要的可以參考一下2023-03-03基于python分享一款地理數(shù)據(jù)可視化神器keplergl
這篇文章主要介紹了分享一款地理數(shù)據(jù)可視化神器keplergl,keplergl是由Uber開(kāi)源的一款地理數(shù)據(jù)可視化工具,通過(guò)keplergl我們可以在Jupyter?notebook中使用,下文分享需要的小伙伴可以參考一下2022-02-02Python+OpenCV圖像處理——實(shí)現(xiàn)輪廓發(fā)現(xiàn)
這篇文章主要介紹了Python+OpenCV實(shí)現(xiàn)輪廓發(fā)現(xiàn),幫助大家更好的利用python處理圖片,感興趣的朋友可以了解下2020-10-10Python實(shí)現(xiàn)爬蟲(chóng)爬取NBA數(shù)據(jù)功能示例
這篇文章主要介紹了Python實(shí)現(xiàn)爬蟲(chóng)爬取NBA數(shù)據(jù)功能,涉及Python針對(duì)URL模塊、字符串、列表遍歷、Excel寫(xiě)入等相關(guān)操作技巧,需要的朋友可以參考下2018-05-05Python matplotlib的使用并自定義colormap的方法
今天小編就為大家分享一篇Python matplotlib的使用并自定義colormap的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12