retrying
是Python編寫的通用重試庫,用於簡化向任何東西添加到重試行爲的任務,最低支持Python3.5!下面來看一下retring
庫的使用:
安裝
pip install retrying
亦或者
easy_install retrying
舉個栗子
下面我們來使用retrying
庫來實現一個簡單的功能,如下:
import random
from retrying import retry
@retry()
def randnum():
num = random.randint(0, 100)
print(num)
if num < 50:
raise Exception("這不是我想要的數")
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
上面代碼中,如果輸出的數字不是大於或等於50的數,將會無間隔不停歇的一直重試!
常用參數
下面我們來看一下retry
裝飾器中一些常用的參數以及用法:
stop_max_attempt_number
最大重試次數。如果stop_max_attempt_number
小於或等於1,那麼將只會重試一次,即整個函數只會執行一次。我們修改一下上面的栗子:
@retry(stop_max_attempt_number=3)
def randnum():
...
如此一來,print(num)
最多隻會執行3次!
stop_max_delay
最大重試時間,單位ms。我們修改一下上面的栗子:
@retry(stop_max_delay=10000)
def randnum():
num = random.randint(0, 100)
print(num)
if num < 101:
raise Exception("這不是我想要的數")
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
上面栗子中,設置最大重試時間爲10秒,那麼此重試機制最多隻會運行10秒,仍未得到結果將不再重試!
wait_fixed
每次重試間隔時間,單位ms。我們修改一下上面的栗子:
@retry(wait_fixed=2000)
def randnum():
...
上面栗子當中,每次重試將會等待2秒後再次執行!
wait_func
wait_func
接收一個可執行函數,返回一個具體的間隔時間數值,單位ms。接收的函數須接收兩個參數:attempt_number
當前運行次數,delay_since_first_attempt_ms
當前重試機制運行時間(單位ms)。如下:
import time
def get_wait_time(attempt_number, delay_since_first_attempt_ms):
return 1000
@retry(wait_func=get_wait_time)
def randnum():
num = random.randint(0, 100)
print(num, time.time())
if num < 101:
raise Exception("這不是我想要的數")
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
如此,同樣實現了每1秒間隔重試一次!
wait_random_min、wait_random_max
每次重試間隔時間(隨機),單位ms。wait_random_min
默認爲0,wait_random_max
默認爲1000!wait_random_min
、wait_random_max
通常成對出現,如果wait_random_min
比wait_random_max
要大,那麼將會引發ValueError
異常!我們修改一下上面的栗子:
@retry(wait_random_min=1000, wait_random_max=2000)
def randnum():
...
上面栗子當中,每次重試將會等待1~2秒(隨機)後再次執行!
wait_exponential_multiplier、wait_exponential_max
每次重試間隔時間,單位ms。間隔時間=2 ^ (index - 1) * wait_exponential_multiplier
(index爲第幾次執行),最大爲wait_exponential_max
!其中wait_exponential_multiplier
默認值爲1,wait_exponential_max
默認值爲1073741823。我們修改一下上面的栗子:
@retry(wait_exponential_multiplier=1000,wait_exponential_max=10000)
def randnum():
num = random.randint(0, 100)
print(num)
if num < 99:
raise Exception("這不是我想要的數")
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
########## 打印如下 ##########
3 1570676268.424493
11 1570676270.4281
51 1570676274.429486
59 1570676282.430687
26 1570676292.432574
43 1570676302.4359198
87 1570676312.437952
4 1570676322.442147
100 1570676332.443142
success, 100
從打印結果可以看到,至2次開始,每次間隔時間以上面的算法遞增,之後以10秒穩定間隔重試
wait_incrementing_start、wait_incrementing_increment
每次重試間隔時間,單位ms。間隔時間 = wait_incrementing_start + wait_incrementing_increment * (index - 1)
(index爲第幾次執行)。其中wait_incrementing_start
默認值爲0,wait_incrementing_increment
默認值爲100。我們修改一下上面的栗子,如下:
import time
@retry(wait_incrementing_start=0, wait_incrementing_increment=1000)
def randnum():
num = random.randint(0, 100)
print(num, time.time())
assert num == 50
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
########## 打印如下 ##########
2 1570757634.768468
64 1570757634.768961
89 1570757635.769883
69 1570757637.7717261
12 1570757640.773932
61 1570757644.776701
50 1570757649.77914
success, 50
retry_on_exception
retry_on_exception
設置指定的錯誤拋出,使用如下:
def is_assertion_error(exception):
return isinstance(exception, AssertionError)
@retry(retry_on_exception=is_assertion_error)
def randnum():
num = random.randint(0, 100)
print(num)
assert num == 50
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
wrap_exception
是否將錯誤包裝成RetryError
錯誤拋出,True是,False非。舉個栗子:
@retry(stop_max_attempt_number=3, wrap_exception=True)
def randnum():
num = random.randint(0, 100)
print(num)
if num < 50:
raise Exception("這不是我想要的數")
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
如果未設置wrap_exception=True
,並且num一直是小於50的情況下,會拋出Exception
錯誤。設置了wrap_exception=True
,將會拋出的是RetryError
錯誤!
retry_on_result
retry_on_result
可以對結果進行判斷,如果retry_on_result
傳遞的函數返回的結果是True則需要重試,否則無需重試。舉個栗子:
def is_result_ok(result):
return result < 101
@retry(stop_max_attempt_number=3, retry_on_result=is_result_ok)
def randnum():
num = random.randint(0, 100)
print(num)
return num
if __name__ == "__main__":
num = randnum()
print("success", num)
上面代碼,重試3次之後將會拋出RetryError
錯誤!
至此,Over~~~