Tenacity:強大的 Python 重試機制庫
更新日期: 2025 年 2 月 13 日
本文為 AI 描述優化 api 設計 系列文,第 6 篇:
- 如何設計一個商品描述優化 API?—— 完整指南
- 設計 AI 優化商品描述的 Prompt
- FastAPI:高效且易用的 Python Web 框架
- 介紹 Uvicorn:高效能 ASGI 伺服器
- Uvicorn 監聽 0.0.0.0,但為何 API 只能用 127.0.0.1 訪問?
- Tenacity:強大的 Python 重試機制庫 👈進度
- FastAPI 建立商品描述優化 API
- 介紹 pytest:Python 測試框架的強大選擇
- Python httpx 完整指南:高效的 HTTP 客戶端
- Pytest-Benchmark:高效能測試的基準分析工具
- 深入解析 monkeypatch:Python 測試中的強大工具
- API 自動化測試與效能優化
建議閱讀本文前,先具備 聊天機器人-建議回復 相關系列文的概念。
在開發 Python 應用程式時,常常會遇到一些不穩定的操作,例如網路請求、資料庫查詢或與外部 API 的交互。
這些操作可能會因暫時性錯誤(如網路不穩或伺服器超時)而失敗,但如果稍後重試,通常可以成功執行。
為了解決這類問題,Python 提供了多種重試機制,但手動實作這些機制可能會導致程式碼冗長且難以維護。
這時候,Tenacity 這個強大的 Python 套件就能發揮作用,它提供了一個靈活且簡單的方式來自動處理重試邏輯,讓開發者可以專注於核心業務邏輯,而不必擔心異常處理的細節。
本文將詳細介紹 Tenacity 的功能、使用方式及最佳實踐,幫助你在開發過程中更高效地處理異常情況。
套件概述
Tenacity 是 Python 的一個功能強大的「重試(retry)機制」庫,它可以讓你設定程式在遇到錯誤時自動進行重試,並且可以靈活地調整重試的條件和策略。例如:
- 設定最大重試次數:可以讓程式最多嘗試執行 N 次,如果嘗試 N 次後仍然失敗,就放棄重試,避免程式一直無限循環。
- 設定重試的間隔時間:例如,程式可以每隔 2 秒 重試一次,而不是無間斷地快速重試,以減少對伺服器或其他資源的壓力。
- 根據錯誤類型決定是否重試:例如,如果程式執行時遇到「伺服器超時錯誤」,則進行重試;但如果遇到「參數錯誤」,則不重試,因為這種錯誤通常不會因為重試而消失。
- 記錄每次重試的狀態:可以在每次重試時記錄日誌,方便開發者後續排查問題,例如:何時發生錯誤、錯誤的內容、總共重試了幾次等等。
由於 Tenacity 提供了簡單直觀的使用方式,開發者只需要透過 裝飾器(decorator)或函數包裝,就可以快速為程式加上「自動重試」的功能,避免因為短暫的錯誤而導致程式失敗。
Tenacity 適用的場景
Tenacity 適用於任何可能因 短暫性錯誤 而失敗的操作,特別是以下這些常見場景:
- 網路請求(API 請求):
- 例如,當你的程式向某個網站發送請求時,網站可能臨時無法連線,如果稍後再嘗試一次,可能就能成功取得資料。
- 資料庫連線:
- 如果你的應用程式需要連接資料庫,而資料庫伺服器偶爾會有連線不穩定的情況,使用 Tenacity 來自動重試,可以減少錯誤發生的機率。
- 讀取文件:
- 假設你的程式需要讀取某個檔案,但檔案可能因為系統鎖定而暫時無法存取,這時可以讓程式稍等幾秒後再試一次。
主要特性
Tenacity 提供了許多強大的功能,讓開發者能夠靈活地控制重試行為,以下是它的幾個核心特性:
自訂重試條件
Tenacity 允許你指定程式在什麼情況下應該進行重試。
例如,你可以設定程式只有在發生「網路錯誤」時才重試,但如果發生「檔案不存在」這類明顯的錯誤,則不進行重試,因為這種錯誤不管重試幾次結果都不會改變。
多種等待策略
當程式進行重試時,並不是所有情況都適合立刻重新執行,有時候適當地「等待一段時間」再重試,會有更好的效果。Tenacity 支援以下幾種常見的等待策略:
- 固定間隔(Fixed Wait):每次重試之間的間隔時間固定,例如每 2 秒 重試一次。
- 指數回退(Exponential Backoff):每次重試的間隔時間逐漸變長,例如第一次重試等待 1 秒,第二次等待 2 秒,第三次等待 4 秒,這樣可以減少對伺服器的壓力。
- 隨機等待(Random Wait):每次重試的間隔時間是隨機的,這在高併發場景下能夠有效減少請求的「集中爆發」問題。
靈活的停止條件
在某些情況下,我們不希望程式無限制地重試,因為這可能會導致 系統資源消耗過多 或 請求卡住太久。
Tenacity 允許開發者設定何時應該停止重試,例如:
- 最多重試 5 次,如果 5 次都失敗,就直接拋出錯誤,不再嘗試。
- 最多等待 30 秒,如果 30 秒內仍然無法成功,則放棄重試。
這樣可以確保程式不會無限循環,避免影響應用程式的整體效能。
回呼函數(Callback Functions)
Tenacity 允許開發者在 每次重試前或重試後 記錄相關資訊,這對於除錯和監控系統運作狀況非常有幫助。例如:
- 在每次重試前記錄日誌,讓開發者知道程式目前的狀態。
- 在重試成功後執行特定動作,例如通知使用者操作已成功完成。
- 在所有重試失敗後執行特定動作,例如發送錯誤報告或觸發警報機制。
簡單易用
Tenacity 提供了一種非常簡單的方式來為函數加入重試機制。
開發者只需要使用 裝飾器(decorator) 或 函數包裝(wrapper),就可以快速地讓函數具有自動重試功能,而不需要手動撰寫 try-except
的邏輯,這大大提高了程式的可讀性與維護性。
Tenacity 安裝與基本用法
安裝 Tenacity
Tenacity 可以透過 pip 直接安裝:
pip install tenacity
基本使用示例
下面是一個簡單的示例,展示如何使用 Tenacity 為函數添加重試機制:
from tenacity import retry, stop_after_attempt, wait_fixed
@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def unstable_function():
print("嘗試執行函數...")
raise Exception("發生錯誤")
unstable_function()
程式解釋:
@retry
:使用裝飾器來標記需要重試的函數。stop_after_attempt(3)
:最多重試 3 次。wait_fixed(2)
:每次重試間隔 2 秒。- 如果函數持續失敗 3 次,異常將會被拋出。
進階用法與策略
設定不同的重試條件
可以根據異常類型來決定是否重試,例如僅針對特定異常進行重試:
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3), retry=retry_if_exception_type(TimeoutError))
def fetch_data():
print("嘗試獲取資料...")
raise TimeoutError("連線超時")
fetch_data()
這段程式碼表示 只有當發生 TimeoutError
時才會進行重試,其他異常則會直接拋出。
使用指數回退策略
指數回退(Exponential Backoff)是一種常見的重試策略,它會在每次重試時逐漸增加等待時間,以減少對伺服器的壓力。
from tenacity import retry, wait_exponential
@retry(wait=wait_exponential(multiplier=1, min=2, max=10))
def unstable_function():
print("執行函數...")
raise Exception("錯誤發生")
unstable_function()
這段程式碼表示:
- 第一次重試後等待 2 秒,第二次等待 4 秒,第三次等待 8 秒,直到最大等待時間 10 秒。
記錄重試資訊
可以透過 before
、after
或 retry_error_callback
來記錄重試行為,例如:
from tenacity import retry, stop_after_attempt, before_log
import logging
logging.basicConfig(level=logging.INFO)
@retry(stop=stop_after_attempt(3), before=before_log(logging.getLogger(), logging.INFO))
def fetch_data():
print("請求 API...")
raise Exception("API 錯誤")
fetch_data()
這樣,每次重試前都會記錄日誌,方便除錯與監控。
Tenacity 的最佳實踐
在實際應用中,使用 Tenacity 時需要考慮以下幾點最佳實踐:
避免無限重試
在某些情況下,請求可能永遠無法成功,因此應該設定 合理的停止條件,例如最大重試次數或最大等待時間。
使用適當的等待策略
如果重試間隔太短,可能會對伺服器造成過大負擔,因此推薦使用 指數回退策略 來優化重試行為。
針對特定錯誤進行重試
不要對所有異常都進行重試,而應該根據錯誤類型來決定,例如只對 TimeoutError
或 ConnectionError
進行重試,以避免不必要的操作。
記錄重試行為
透過日誌記錄重試次數與錯誤訊息,可以幫助開發者快速定位問題並進行調整。
結論
Tenacity 是一款強大且靈活的 Python 重試機制庫,它讓開發者能夠輕鬆地為函數添加重試邏輯,並提供了多種策略來控制重試行為。
在處理網路請求、API 交互或其他不穩定的操作時,使用 Tenacity 可以大幅提升程式的可靠性,減少因暫時性錯誤導致的失敗。
如果你的應用程式經常遇到臨時性錯誤或不穩定的外部請求,那麼 Tenacity 絕對是一個值得學習與使用的工具! 🚀