亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

python try...finally...的實(shí)現(xiàn)方法

瀏覽:148日期:2022-07-04 13:30:36

1. 關(guān)于 try.. finally..

假如上帝用 python 為每一個(gè)來(lái)到世界的生物編寫程序,那么除去中間過程的種種復(fù)雜實(shí)現(xiàn),最不可避免的就是要保證每個(gè)實(shí)例最后都要掛掉。代碼可簡(jiǎn)寫如下:

try: born() # 出生 # 正常降臨世界 # do something..except ValueError: # 安排錯(cuò)誤 # do something...except AttributeError: # 特征錯(cuò)誤 # do something...except TypeError: # 種類錯(cuò)誤 # do something...... # 等等雜七雜八的錯(cuò)誤finally: go_die() # 掛掉 come_to_see_me() # 然后來(lái)見我 reincarnate() # 下一輪,安排!

這就是 finally 的作用和實(shí)例。就算捕獲異常后再次出現(xiàn)異常,最終也能保證 go_die 方法會(huì)執(zhí)行,但是,如果 go_die 方法出現(xiàn)錯(cuò)誤,那么就不能正常去見上帝了。為了保證每個(gè)生物(不管有沒有掛掉)都能見到上帝他老人家,并開始下一個(gè)輪回(不管有沒有見到),需要做如下處理:

...finally: try: go_die() finally: try: come_to_see_me() finally: reincarnate()

OK,功能雖然實(shí)現(xiàn)了,但按照 The Zen of Python 所說(shuō):Flat is better than nested.(扁平優(yōu)于嵌套),那么這段代碼就略顯丑陋了。為了遵循 python 美學(xué),我們可以對(duì)這段進(jìn)行優(yōu)化,使它看起來(lái)更為美觀。

2. 錯(cuò)誤的上下文:__context__

在此之前,需要引入一個(gè)新的概念: __context__,__context__ 的字面意思就是上下文,它屬于錯(cuò)誤的一個(gè)屬性。在錯(cuò)誤捕獲中,它意味著當(dāng)你處理一個(gè)錯(cuò)誤時(shí),另一個(gè)錯(cuò)誤發(fā)生了。也就是說(shuō),你所捕獲的錯(cuò)誤雖然被成功捕獲了,但當(dāng)捕獲完成時(shí),你的一些操作導(dǎo)致另一個(gè)錯(cuò)誤發(fā)生,而這個(gè)錯(cuò)誤并沒有被捕獲。通常情況下,如果處理的好,那么當(dāng)前錯(cuò)誤的 __context__ 的值為 None,如果處理不好那就是你所捕獲的錯(cuò)誤。比如下面的代碼:

def type_err(): raise TypeError(’this is a type error.’)def after_type_err(): raise ValueError(’this is a value error.’)try: type_err()except TypeError: after_type_err()

執(zhí)行結(jié)果為:

Traceback (most recent call last): File '<ipython-input-4-189a22d65266>', line 8, in <module> type_err() File '<ipython-input-4-189a22d65266>', line 2, in type_err raise TypeError(’this is a type error.’)TypeError: this is a type error.During handling of the above exception, another exception occurred:Traceback (most recent call last): File 'C:UserslineuAppDataLocalProgramsPythonPython37libsite-packagesIPythoncoreinteractiveshell.py', line 3326, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File '<ipython-input-4-189a22d65266>', line 10, in <module> after_type_err() File '<ipython-input-4-189a22d65266>', line 5, in after_type_err raise ValueError(’this is a value error.’)ValueError: this is a value error.

在上面的錯(cuò)誤信息中,當(dāng)前錯(cuò)誤類型為 ValueError,它的 __context__ 屬性值為 TypeError 實(shí)例,而 TypeError 實(shí)例的 __context__ 為 None。

3. FinalExecutor:優(yōu)雅的 finally

有了 __context__ 的概念,我們就可以基于此實(shí)現(xiàn)一個(gè)優(yōu)雅的“輪回”了。基本思路為:依次執(zhí)行方法,如果方法報(bào)錯(cuò),那么就將該錯(cuò)誤的 __context__ 值設(shè)置為上一個(gè)錯(cuò)誤(如果有)。最后等到所有方法執(zhí)行完畢,再拋出最后一個(gè)錯(cuò)誤,那么此時(shí)的錯(cuò)誤將包含所有可能被引發(fā)的錯(cuò)誤信息。具體代碼如下:

class FinalExecutor(object): '''終極執(zhí)行器 用于確保你所有的方法都會(huì)被執(zhí)行(不管中途有沒有方法報(bào)錯(cuò)) 同時(shí)能看到正確的錯(cuò)誤信息 ''' def __init__(self): self.last_err = None # 保存最近發(fā)生的錯(cuò)誤 def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): # 如果有發(fā)生錯(cuò)誤,則拋出 if self.last_err: raise self.last_err def call(self, func, *args, **kwargs): '''調(diào)用執(zhí)行方法''' try: func(*args, **kwargs) except Exception as e: # Exception 捕獲所有繼承自它或它子類的錯(cuò)誤類型 # 捕獲它等于捕獲幾乎所有錯(cuò)誤 if self.last_err:# 將本次錯(cuò)誤的上下文定義為上一次錯(cuò)誤e.__context__ = self.last_err # 更新為當(dāng)前錯(cuò)誤 self.last_err = e

我們的終極執(zhí)行器使用示例為:

# 定義 3 個(gè)方法用于測(cè)試def type_err(): print(’type error’) raise TypeError(’x’)def value_err(): print(’value error’) raise ValueError(’x’)def attr_err(): print(’attr error’) raise AttributeError(’x’)# 使用 with 語(yǔ)句來(lái)啟動(dòng)終極執(zhí)行器with FinalExecutor() as e: e.call(type_err) e.call(value_err) e.call(attr_err)

運(yùn)行可以看到方法最終都被執(zhí)行了,且錯(cuò)誤信息一個(gè)不漏:

type errorvalue errorattr errorTraceback (most recent call last): File '<ipython-input-5-1b07c576630b>', line 19, in call func(*args, **kwargs) File '<ipython-input-6-d602d89ed0e7>', line 3, in type_err raise TypeError(’x’)TypeError: xDuring handling of the above exception, another exception occurred:Traceback (most recent call last): File '<ipython-input-5-1b07c576630b>', line 19, in call func(*args, **kwargs) File '<ipython-input-6-d602d89ed0e7>', line 8, in value_err raise ValueError(’x’)ValueError: xDuring handling of the above exception, another exception occurred:Traceback (most recent call last): File 'C:UserslineuAppDataLocalProgramsPythonPython37libsite-packagesIPythoncoreinteractiveshell.py', line 3326, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File '<ipython-input-6-d602d89ed0e7>', line 19, in <module> e.call(attr_err) File '<ipython-input-5-1b07c576630b>', line 15, in __exit__ raise self.last_err File '<ipython-input-5-1b07c576630b>', line 19, in call func(*args, **kwargs) File '<ipython-input-6-d602d89ed0e7>', line 13, in attr_err raise AttributeError(’x’)AttributeError: x

4. 使用 ExitStack

有了我們的終極執(zhí)行器,上帝就可以優(yōu)雅的寫代碼了。為了讓每個(gè)人都能這樣優(yōu)雅的寫 python 代碼,python 為我們提供了一個(gè)封裝好的功能,當(dāng)然它的實(shí)現(xiàn)要比我們的終極執(zhí)行器復(fù)雜一些(考慮的也更周到一些~)。我們可以通過 contextlib 模塊導(dǎo)入該方法并使用:

from contextlib import ExitStackwith ExitStack() as stack: stack.callback(type_err) stack.callback(value_err) stack.callback(attr_err)

注意該 ExitStack 與 FinalExecutor 不同的是,它是倒序執(zhí)行的。

以上就是python try...finally...的實(shí)現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于python try...finally的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 日本特级黄毛片毛片视频 | 美日韩一级 | 1024成人 | 古代的一a一片一级一片 | 午夜性色一区二区三区不卡视频 | 国产综合久久一区二区三区 | 国产黄大片在线视频 | 黑人香蕉又粗又大视频免费 | 日韩精品片 | 国产一级一片免费播放刺激 | 欧美男女爱爱视频 | 无码中文字幕乱在线观看 | 亚洲第一综合 | 国产精品久久久久久久久久久威 | 国产精品久久精品视 | 久久婷婷午色综合夜啪 | 美女白丝超短裙被输出动态图 | 国产亚洲精品免费 | 亚洲色图视频在线 | 手机看片欧美 | 欧美日本一道免费一区三区 | 久久成人影视 | 国产妇女性爽视频免费 | 性视频免费视频大全 | 日本xxx片免费高清在线 | 一级免费黄色 | 国产精品国产福利国产秒拍 | 久国产精品视频 | 国产精品福利在线观看免费不卡 | 精品视频在线观看 | 国产黄色一级片 | 国模久久 | 久久久久久一级毛片免费野外 | 美国黄色片免费看 | 久操视频免费看 | 精品综合网 | 欧美特黄高清免费观看的 | 国产高清亚洲精品26u | 爱爱网站在线观看免费 | 国产欧美日韩成人 | 日韩伦理中文字幕 |