@retry装饰器能统一处理临时性失败,但需控制重试次数、间隔、异常类型及超时,避免雪崩;仅对可恢复错误(如连接超时)有效,须显式指定异常、加抖动与日志,生产环境推荐tenacity。

直接说结论:用 @retry 装饰器能统一处理网络请求、数据库操作等临时性失败,但必须控制重试次数、间隔和异常类型,否则可能雪崩或无限循环。
为什么不能无脑 catch-all 重试
重试只对可恢复错误有意义,比如 requests.exceptions.ConnectionError 或 sqlite3.OperationalError;而 ValueError、TypeError 这类逻辑错误重试一百次也没用,反而掩盖真正问题。
- 默认只重试指定的异常类,别用
Exception通配 - 重试前加随机抖动(jitter),避免大量请求同时涌向下游服务
- 超时时间要显式设置,比如
requests.get(..., timeout=5),否则重试可能卡死
装饰器参数怎么设才合理
@retry 至少得支持 max_attempts、delay、backoff 和 exceptions 四个参数。实际用的时候:
-
max_attempts=3是常见起点,超过三次大概率是真故障 -
delay=1秒起步,配合backoff=2实现指数退避(1s → 2s → 4s) -
exceptions=(requests.exceptions.Timeout, requests.exceptions.ConnectionError)显式声明 - 别忘了加
logger参数,方便定位哪次重试失败了
自己写还是用第三方库
自己实现够轻量,适合简单场景;但生产环境建议用 tenacity —— 它内置了 jitter、结果过滤、异步支持,且经过充分测试。
立即学习“Python免费学习笔记(深入)”;
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
比如用 tenacity 写一个带 jitter 的重试:
from tenacity import retry, stop_after_attempt, wait_exponential_jitter
from requests import get
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential_jitter(initial=1, max=8)
)
def fetch_data(url):
return get(url, timeout=5).json()
注意 wait_exponential_jitter 里的 max=8 很关键:防止第 3 次重试等太久,拖慢整个调用链。
异步函数怎么加重试
同步装饰器套在 async def 函数上会报错:RuntimeWarning: coroutine 'xxx' was never awaited。
- 必须用支持协程的重试库,比如
tenacity的@retry配合await - 自己实现的话,装饰器内部得用
await调用原函数,且返回值是coroutine对象 - 别在重试逻辑里混用
time.sleep(),要用asyncio.sleep()
重试的边界感容易模糊——比如上游已超时,你还重试,只是把压力转嫁给别人。重试不是兜底,是给短暂抖动留的余地。

















