網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Python異常處理如何才能寫(xiě)得優(yōu)雅(retrying模塊)_python
作者:Python學(xué)習(xí)與數(shù)據(jù)挖掘 ? 更新時(shí)間: 2022-05-25 編程語(yǔ)言前言
在寫(xiě)程序時(shí),我們會(huì)經(jīng)常碰到程序出現(xiàn)異常,這時(shí)候我們就不得不處理這些異常,以保證程序的健壯性。
處理異常的版本有以下幾種,你通常的做法是哪種?
不負(fù)責(zé)任版本
這種情況下,不作任何處理,任由程序報(bào)錯(cuò),從而導(dǎo)致程序中斷。
針對(duì)簡(jiǎn)單的程序,這樣做沒(méi)什么問(wèn)題,大不了我遇到問(wèn)題之后把問(wèn)題解決,然后重新運(yùn)行。但是如果是復(fù)雜的系統(tǒng)就會(huì)很麻煩了,可能你一個(gè)異常阻塞了系統(tǒng)的運(yùn)行,帶來(lái)災(zāi)難性的后果。
簡(jiǎn)單處理版本
簡(jiǎn)單處理版本,就是加上異常捕獲,在發(fā)生異常時(shí)記錄日志,時(shí)候可以通過(guò)日志來(lái)定位異常。
def do_something(): ? ? pass def log_error(xxx): ? ? pass try: ? ?do_something() except: ? ? log_error(xxxx)
改進(jìn)處理版本
對(duì)于簡(jiǎn)單處理版本做了改進(jìn),增加重試次數(shù)。這個(gè)在爬蟲(chóng)程序中比較常見(jiàn),第一次請(qǐng)求超時(shí),可能過(guò)一會(huì)再請(qǐng)求就成功了,所以重試幾次可能會(huì)消除異常。
attempts = 0 success = False while attempts < 3 and not success: try: do_something() success = True except: attempts += 1 if attempts == 3: break
但是這樣做仍然不夠優(yōu)雅,你可能要在很多地方去寫(xiě)這種重試的硬編碼,程序看起來(lái)亂糟糟的。
今天就給大家介紹一個(gè)第三方模塊 —— retrying。它是對(duì)程序中異常重試的一種優(yōu)雅的解決方案。
安裝與使用
安裝
安裝命令還是那么平淡無(wú)奇:
pip install retrying
使用
下面給大家介紹一下這個(gè)裝飾函數(shù)有哪些可以使用的參數(shù)。
生命不息,奮斗不止
retrying 提供一個(gè)裝飾器函數(shù) retry,被裝飾的函數(shù)會(huì)在運(yùn)行失敗的情況下重新執(zhí)行,默認(rèn)一直報(bào)錯(cuò)就一直重試。
import random from retrying import retry @retry def do_something_unreliable(): if random.randint(0, 10) > 1: print("just have a test") raise IOError("raise exception!") else: return "good job!" print(do_something_unreliable())
運(yùn)行這個(gè)程序,大家可以看到每次打印“just have a test”這句話的次數(shù)都不一樣。這是由于我們程序中只要隨機(jī)整數(shù)大于1就會(huì)打印并且拋出異常。但是由于我們有裝飾器函數(shù) retry,所以在發(fā)生異常就會(huì)重新再次執(zhí)行方法,直到隨機(jī)整數(shù)大于1,就會(huì)打印“good job!”。
做人不能太固執(zhí)
這種無(wú)休止地重試,簡(jiǎn)直是浪費(fèi)生命,浪費(fèi)資源。我們要建設(shè)綠色家園,所以不妨加點(diǎn)限制:
# 最大重試次數(shù) @retry(stop_max_attempt_number=5) def do_something_limited(): print("do something several times") raise Exception("raise exception") do_something_limited()
珍惜有限的時(shí)間
一寸光陰一寸金,寸金難買(mǎi)寸光陰。我們要珍惜有限的時(shí)間,所以不妨給我們的重試加個(gè)時(shí)間限制:
# 限制最長(zhǎng)重試時(shí)間(從執(zhí)行方法開(kāi)始計(jì)算) @retry(stop_max_delay=5000) def do_something_in_time(): print("do something in time") raise Exception("raise exception") do_something_in_time()
駐足欣賞路上風(fēng)景
人生匆匆數(shù)十載,不要一路狂奔而忘記欣賞路邊的美景,有時(shí)候我們需要花點(diǎn)時(shí)間來(lái)欣賞一路的美景:
# 設(shè)置固定重試時(shí)間 @retry(wait_fixed=2000) def wait_fixed_time(): print("wait") raise Exception("raise exception") wait_fixed_time()
給失敗設(shè)個(gè)限
雖說(shuō)我們需要屢敗屢戰(zhàn)的韌性,但是失敗也要有個(gè)限度,不能在失敗中度過(guò)一生:
# 設(shè)置重試時(shí)間的隨機(jī)范圍 @retry(wait_random_min=1000,wait_random_max=2000) def wait_random_time(): print("wait") raise Exception("raise exception") wait_random_time()
有些人值得等待
茫茫人海中,我就是要等到那個(gè)對(duì)的人:
# 根據(jù)異常重試 def retry_if_io_error(exception): return isinstance(exception, IOError) # 設(shè)置特定異常類(lèi)型重試 @retry(retry_on_exception=retry_if_io_error) def retry_special_error(): print("retry io error") raise IOError("raise exception") retry_special_error()
我們自己定義一個(gè)函數(shù),判斷異常類(lèi)型,然后將函數(shù)作為參數(shù)傳給裝飾函數(shù) retry ,如果異常類(lèi)型符合,就會(huì)進(jìn)行重試。
有些結(jié)果是我們希望見(jiàn)到的
人生并不是一帆風(fēng)順,有些時(shí)候我們會(huì)遇到挫折,這些挫折也許在一開(kāi)始就是我們想要的:
# 通過(guò)返回值判斷是否重試 def retry_if_result_none(result): """Return True if we should retry (in this case when result is None), False otherwise""" # return result is None if result =="111": return True @retry(retry_on_result=retry_if_result_none) def might_return_none(): print("Retry forever ignoring Exceptions with no wait if return value is None") return "111" might_return_none()
這里我們定義了一個(gè)判斷返回值的函數(shù),然后將這個(gè)函數(shù)作為參數(shù)傳給 retry 裝飾函數(shù)。當(dāng)結(jié)果返回是“111”時(shí),就會(huì)一直重試執(zhí)行 might_return_none 函數(shù)。
生活豐富多彩,并不單調(diào)
我們的生活是豐富多彩的,從來(lái)都沒(méi)有很單調(diào)。所以上面這些參數(shù),我們可以隨意組合使用,并不限定每次只能用一個(gè)。比如你可以限定遇到 IOError 時(shí)進(jìn)行重試,并且重試次數(shù)最多5次。
總結(jié)
人生不可重來(lái),但是Python可以重試!
我已經(jīng)將retrying 這個(gè)裝飾函數(shù)的使用方法毫無(wú)保留地奉獻(xiàn)給各位看官了,趕快用起來(lái)吧!
原文鏈接:https://blog.csdn.net/weixin_38037405/article/details/123198180
相關(guān)推薦
- 2022-09-06 golang實(shí)現(xiàn)命令行程序的使用幫助功能_Golang
- 2022-05-08 python列表的構(gòu)造方法list()_python
- 2022-11-21 Qt實(shí)現(xiàn)小功能之圓形進(jìn)度條的方法詳解_C 語(yǔ)言
- 2022-05-06 教你使用zabbix?api批量添加數(shù)百臺(tái)監(jiān)控主機(jī)的方法_zabbix
- 2022-07-07 Django加載配置的過(guò)程詳解_python
- 2022-04-22 如何讓electron收到消息發(fā)出聲音
- 2022-10-15 Qt?TCP網(wǎng)絡(luò)通信學(xué)習(xí)_C 語(yǔ)言
- 2022-07-08 Python如何通過(guò)地址獲取變量_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支