Python異常處理如何才能寫得優(yōu)雅(retrying模塊)
前言
在寫程序時,我們會經(jīng)常碰到程序出現(xiàn)異常,這時候我們就不得不處理這些異常,以保證程序的健壯性。
處理異常的版本有以下幾種,你通常的做法是哪種?
不負責任版本
這種情況下,不作任何處理,任由程序報錯,從而導致程序中斷。
針對簡單的程序,這樣做沒什么問題,大不了我遇到問題之后把問題解決,然后重新運行。但是如果是復(fù)雜的系統(tǒng)就會很麻煩了,可能你一個異常阻塞了系統(tǒng)的運行,帶來災(zāi)難性的后果。
簡單處理版本
簡單處理版本,就是加上異常捕獲,在發(fā)生異常時記錄日志,時候可以通過日志來定位異常。
def do_something(): ? ? pass def log_error(xxx): ? ? pass try: ? ?do_something() except: ? ? log_error(xxxx)
改進處理版本
對于簡單處理版本做了改進,增加重試次數(shù)。這個在爬蟲程序中比較常見,第一次請求超時,可能過一會再請求就成功了,所以重試幾次可能會消除異常。
attempts = 0
success = False
while attempts < 3 and not success:
try:
do_something()
success = True
except:
attempts += 1
if attempts == 3:
break
但是這樣做仍然不夠優(yōu)雅,你可能要在很多地方去寫這種重試的硬編碼,程序看起來亂糟糟的。
今天就給大家介紹一個第三方模塊 —— retrying。它是對程序中異常重試的一種優(yōu)雅的解決方案。
安裝與使用
安裝
安裝命令還是那么平淡無奇:
pip install retrying
使用
下面給大家介紹一下這個裝飾函數(shù)有哪些可以使用的參數(shù)。
生命不息,奮斗不止
retrying 提供一個裝飾器函數(shù) retry,被裝飾的函數(shù)會在運行失敗的情況下重新執(zhí)行,默認一直報錯就一直重試。
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())
運行這個程序,大家可以看到每次打印“just have a test”這句話的次數(shù)都不一樣。這是由于我們程序中只要隨機整數(shù)大于1就會打印并且拋出異常。但是由于我們有裝飾器函數(shù) retry,所以在發(fā)生異常就會重新再次執(zhí)行方法,直到隨機整數(shù)大于1,就會打印“good job!”。
做人不能太固執(zhí)
這種無休止地重試,簡直是浪費生命,浪費資源。我們要建設(shè)綠色家園,所以不妨加點限制:
# 最大重試次數(shù)
@retry(stop_max_attempt_number=5)
def do_something_limited():
print("do something several times")
raise Exception("raise exception")
do_something_limited()
珍惜有限的時間
一寸光陰一寸金,寸金難買寸光陰。我們要珍惜有限的時間,所以不妨給我們的重試加個時間限制:
# 限制最長重試時間(從執(zhí)行方法開始計算)
@retry(stop_max_delay=5000)
def do_something_in_time():
print("do something in time")
raise Exception("raise exception")
do_something_in_time()
駐足欣賞路上風景
人生匆匆數(shù)十載,不要一路狂奔而忘記欣賞路邊的美景,有時候我們需要花點時間來欣賞一路的美景:
# 設(shè)置固定重試時間
@retry(wait_fixed=2000)
def wait_fixed_time():
print("wait")
raise Exception("raise exception")
wait_fixed_time()
給失敗設(shè)個限
雖說我們需要屢敗屢戰(zhàn)的韌性,但是失敗也要有個限度,不能在失敗中度過一生:
# 設(shè)置重試時間的隨機范圍
@retry(wait_random_min=1000,wait_random_max=2000)
def wait_random_time():
print("wait")
raise Exception("raise exception")
wait_random_time()
有些人值得等待
茫茫人海中,我就是要等到那個對的人:
# 根據(jù)異常重試
def retry_if_io_error(exception):
return isinstance(exception, IOError)
# 設(shè)置特定異常類型重試
@retry(retry_on_exception=retry_if_io_error)
def retry_special_error():
print("retry io error")
raise IOError("raise exception")
retry_special_error()
我們自己定義一個函數(shù),判斷異常類型,然后將函數(shù)作為參數(shù)傳給裝飾函數(shù) retry ,如果異常類型符合,就會進行重試。
有些結(jié)果是我們希望見到的
人生并不是一帆風順,有些時候我們會遇到挫折,這些挫折也許在一開始就是我們想要的:
# 通過返回值判斷是否重試
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()
這里我們定義了一個判斷返回值的函數(shù),然后將這個函數(shù)作為參數(shù)傳給 retry 裝飾函數(shù)。當結(jié)果返回是“111”時,就會一直重試執(zhí)行 might_return_none 函數(shù)。
生活豐富多彩,并不單調(diào)
我們的生活是豐富多彩的,從來都沒有很單調(diào)。所以上面這些參數(shù),我們可以隨意組合使用,并不限定每次只能用一個。比如你可以限定遇到 IOError 時進行重試,并且重試次數(shù)最多5次。
總結(jié)
人生不可重來,但是Python可以重試!
我已經(jīng)將retrying 這個裝飾函數(shù)的使用方法毫無保留地奉獻給各位看官了,趕快用起來吧!
到此這篇關(guān)于Python異常處理如何寫得優(yōu)雅的文章就介紹到這了,更多相關(guān)Python異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實現(xiàn)ipsec開權(quán)限實例
這篇文章主要介紹了python實現(xiàn)ipsec開權(quán)限的方法,彌補了windows自帶的命令行工具netsh ipsec static add filter不支持批量添加及添加重復(fù)規(guī)則的不足,非常具有實用價值,需要的朋友可以參考下2014-11-11
淺談關(guān)于Python3中venv虛擬環(huán)境
這篇文章主要介紹了淺談關(guān)于Python3中venv虛擬環(huán)境,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
淺談pandas中DataFrame關(guān)于顯示值省略的解決方法
下面小編就為大家分享一篇淺談pandas中DataFrame關(guān)于顯示值省略的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04
python pandas中對Series數(shù)據(jù)進行軸向連接的實例
今天小編就為大家分享一篇python pandas中對Series數(shù)據(jù)進行軸向連接的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06
python算法學習雙曲嵌入論文代碼實現(xiàn)數(shù)據(jù)集介紹
由于雙曲嵌入相關(guān)的文章已經(jīng)有了一系列的代碼。本篇博客主要目的實現(xiàn)最開始的雙曲嵌入論文,將論文中有些直接寫出來的內(nèi)容進行了細節(jié)的推導,同時實現(xiàn)對應(yīng)的代碼2021-11-11

