當前位置:
首頁 > 知識 > Python退避及重試裝飾器:backoff

Python退避及重試裝飾器:backoff


小編注


退避,指的是操作失敗,等一段時間再重試,而不是立即重試的行為。其意義在於期望被調用的資源能夠在這段時間裡自行恢復。


退避和重試的函數裝飾器



此模塊提供函數裝飾器,該函數裝飾器可用於包裝函數,以便函數重試直到滿足某些條件為止。當訪問可能出現間歇性故障的不可靠資源(如網路資源和外部API)時,它應該有用。一般來說,它還可以用於外部生成內容的動態輪詢資源。


裝飾器既支持同步代碼的常規功能,也支持非同步代碼的asyncio的協同程序。


示例


由於Kenneth Reitz的requests模塊已經成為Python中同步HTTP客戶端的行業標準,因此下面使用該模塊編寫了網路示例,但是backoff模塊根本不需要它。


@backoff.on_exception


當指定異常被引發時,使用

on_exception

裝飾器重試。這裡有一個例子,當出現任何

requests

異常時,使用指數退避(即退避時間指數增長):


對於需要多個異常類型採取相同退避行為的情況,裝飾器還將接受異常元組:



放棄的條件


可選參數可以指定要放棄的條件。


關鍵字參數

max_time

指定在放棄之前的總時間的最大秒數。



關鍵字參數

max_tries

指定在放棄之前對目標函數進行調用的最大次數。



在某些情況下,可能需要檢查引發異常的實例本身,以確定它是否滿足可重試條件。

giveup

關鍵字參數可用於指定一個函數,該函數接受異常並在不應該重試異常時返回真值:



當放棄事件發生時,問題中的異常重新引發,因此調用on_exception-decorated函數的代碼可能仍然需要執行異常處理。



@backoff.on_predicate


當目標函數返回值符合某個特定條件時,

on_predicate

裝飾器會安排重試。當為外部生成內容輪詢資源時,這可能是有用的。

下面是一個例子,當目標函數的返回值為空列表時,使用斐波那契序列退避(退避時間滿足):



在初始化等待生成器時傳遞額外的關鍵字參數,因此在初始化fibo生成器時,上面的

max_value

參數作為關鍵字參數傳遞。


當未指定斷言函數時,默認做返回值的假值測試,因此上面可以寫的更簡潔些:



更簡單地說,一個繼續每秒鐘輪詢直到得到非假結果的函數可以像這樣定義:



Jitter


jitter演算法可以向任何一個退避裝飾器提供

jitter

關鍵字參數。這個參數應該是一個函數,接受原始的退避值並返回它的jittered的對應項。


從1.2版開始,默認的jitter函數

backoff.full_jitter

實現了AWS架構博客的指數退避和Jitter帖子中定義的「Full Jitter」演算法。注意,使用此演算法,等待生成器所產生的時間實際上是等待的最大時間量。


以前版本的退避默認添加隨機數毫秒(高達1s)到原始睡眠值。如果需要,這種行為現在可以作為

backoff.random_jitter


使用多個裝飾器


還可以組合退避裝飾器以指定不同情況下的不同退避行為:



運行時配置


裝飾函數

on_excep

tion

on_predicate

通常在導入時確定參數。當關鍵字參數作為常量值傳遞時,這很好,但是假設我們想要查閱帶有配置選項的字典,這些配置選項僅在運行時可用。相關值在導入時不可用。取而代之的是,裝飾函數可以通過在運行時執行函數來獲得參數值:



事件處理


兩個backoff裝飾器都可以選擇使用關鍵字參數

on_success

on_backoff

on_giveup

接受事件處理程序函數。這在報告統計或執行其他自定義日誌方面可能有用。


處理程序必須是一個接受一個字典參數的一元簽名的可調用文件。此字典包含調用的詳細信息。有效鍵包括:



  • target:引用調用的函數或方法



  • args:func的位置參數



  • kwargs : func的關鍵字參數



  • tries: 到目前為止的調用次數



  • elapsed: 到現在為止經過的時間



  • wait: 等待秒(僅

    on_backoff

    處理)



  • value: 觸發退避值(僅用

    on_predicate

    裝飾器)


列印回退事件的細節的處理程序可以實現如下:


每個事件類型的多個處理程序


在所有情況下,處理函數的迭代被接受,依次調用它們。例如,你可以提供一個簡單的處理函數列表,作為

on_backoff

關鍵字參數的值:



獲取異常信息


on_exception

裝飾器的情況下,所有

on_backoff

on_giveup

處理程序都從異常塊中調用,以處理異常。因此,異常信息可以通過python標準庫(特別是

sys.exc_info()

traceback

模塊)提供給處理函數。


非同步代碼


要在基於asyncio的非同步代碼中使用backoff,您只需要將

backoff.on_exception

backoff.on_predicate

應用於協同常式。您還可以使用介面是相同的

on_success

on_backoff

on_giveup

事件處理程序的協同程序。


下面的示例使用aiohttp 非同步HTTP Client/Server庫。


採用Python 3.5及以上的

async def

await

語法:



如果使用Python 3.4,可以使用@asyncio.coroutine和yield from:



日誌配置


錯誤和回退和重試嘗試被記錄到「退避」記錄器。默認情況下,此記錄器配置為NullHandler,因此除非配置處理程序,否則將沒有輸出。從編程上講,這可以用簡單的方法來完成:



記錄默認級別是INFO,它對應於重試事件發生時的日誌記錄。如果您只希望在發生giveup事件時記錄,則將記錄器級別設置為ERROR。





英文原文:https://github.com/litl/backoff/


譯者:張新英



喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python程序員 的精彩文章:

為什麼開源失敗了
Python流處理

TAG:Python程序員 |