Python-重試機制

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_minwait_random_max

每次重試間隔時間(隨機),單位ms。wait_random_min默認爲0,wait_random_max默認爲1000!wait_random_minwait_random_max通常成對出現,如果wait_random_minwait_random_max要大,那麼將會引發ValueError異常!我們修改一下上面的栗子:

@retry(wait_random_min=1000, wait_random_max=2000)
def randnum():
    ...

上面栗子當中,每次重試將會等待1~2秒(隨機)後再次執行!

wait_exponential_multiplierwait_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_startwait_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~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章