Python重試任務模塊tenacity

 

軟硬件環境

  • windows 11 64bits

  •  python 3.6

  • tenacity

簡介

在實際應用中,經常會碰到在web請求時,因爲網絡的不穩定,會有請求超時的問題,這時候,一般都是自己去實現重試請求的邏輯,直到得到響應或者超時。雖然這樣的邏輯並不複雜,但是代碼寫起來卻不那麼優雅,不那麼pythonic

tenacity是一個重試庫,使用python語言編寫,它能夠讓我們在任務的重試操作中變得非常簡單,使用的是Apache 2.0開源協議。

tenacity有如下特性

  • 裝飾器API

  • 可指定停止條件

  • 可指定等待條件

  • 自定義異常時的重試

  • 自定義特定返回值的重試

  • 在協程中使用

模塊安裝

使用pip安裝tenacity

pip install tenacity

示例代碼

無條件重試

這是tenacity最基本的用法,在task方法中使用裝飾器@retry,當task出現異常時,我們就重新運行task,這裏沒加任何限制,如果異常一直出現,task就會一直運行下去

from tenacity import retry
import time
@retry
def task():
    print("task running ... ")
    time.sleep(1)
    raise Exception
task()

執行上述代碼,得到

task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ... 
task running ...
.
.
.

設定停止條件

通過方法stop_after_attempt指定重試的次數,如下的3次

import time
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
def task():
    print("task running ... ")
    time.sleep(1)
    raise Exception
task()

重試三次之後就報錯了

或者使用方法stop_after_delay指定重試多長時候後停止,如下的3秒

from tenacity import retry, stop_after_delay
@retry(stop=stop_after_delay(3))
def task():
    print("task running ... ")
    raise Exception
task()

一直重試很多次,3秒後還沒成功,就結束重試

還可以將stop_after_delaystop_after_attempt組合起來用,如下的代碼,只要其中一個條件滿足,task就停止運行

import time
from tenacity import retry, stop_after_attempt, stop_after_delay
@retry(stop=(stop_after_delay(10) | stop_after_attempt(5)))
def task():
    print("task running ... ")
    time.sleep(1)
    raise Exception
task()

設定等待時間

使用方法wait_fixed來指定重試時等待的時間,如下代碼中的3秒,每一次重試task前都要等待3秒鐘

from tenacity import retry, wait_fixed
@retry(wait=wait_fixed(3))
def task():
    print("task running ... ")
    raise Exception
task()

如下,可以看到,每隔3秒重試一次

使用方法wait_random(min, max),在minmax之間隨機取值,每一次task重試前就等待這個隨機值,單位是秒

from tenacity import retry, wait_random
@retry(wait=wait_random(min=1, max=3))
def task():
    print("task running ... ")
    raise Exception
task()

時間有1 2 3s的

當然,上面2中種方法也是可以結合起來用的

from tenacity import retry, wait_fixed, wait_random
@retry(wait=wait_fixed(3) + wait_random(0, 2))
def task():
    print("task running ... ")
    raise Exception
task()

 

什麼情況下重試

可以通過retry_if_exception_type指定特定類型的異常出現時,任務才重試

from tenacity import retry, retry_if_exception_type
@retry(retry=retry_if_exception_type(IOError))
def task():
    print("task running ... ")
    raise Exception
task()

重試錯誤後的異常拋出

出現異常後,會進行重試,若重試後還是失敗,默認情況下,往上拋出的異常會變成RetryError,而不是最根本的原因。因此可以加一個參數reraise=True,使得當重試失敗後,往外拋出的異常還是原來的那個異常。

from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3), reraise=True)
def task():
    print("task running ... ")
    raise Exception
task()

 默認是false,false是重試錯誤

在重試前執行動作

tenacity可以在任務重試前後執行某些動作,這裏以加日誌爲例

from tenacity import retry, stop_after_attempt, before_log
import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logger = logging.getLogger(__name__)
@retry(stop=stop_after_attempt(3), before=before_log(logger=logger, log_level=logging.DEBUG))
def task():
    print("task running ... ")
    raise Exception
task()

 tenacity重試後的操作類似,如下

from tenacity import retry, stop_after_attempt, after_log
import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logger = logging.getLogger(__name__)
@retry(stop=stop_after_attempt(3), after=after_log(logger=logger, log_level=logging.DEBUG))
def task():
    print("task running ... ")
    raise Exception
task()

tenacity

Python實用模塊專題

更多有用的python模塊,請移步

https://xugaoxiang.com/category/python/modules/

參考資料

  • https://github.com/jd/tenacity

 http://www.taodudu.cc/news/show-4122770.html?action=onClick

 

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