用tenacity比手写while循环靠谱,它专治网络抖动、临时502、DNS超时等问题,支持异常类型过滤、指数退避、重试上限等精细控制。

requests请求失败后怎么自动重试?用tenacity比手写while循环靠谱
直接结论:别自己写time.sleep + try/except套三层,tenacity专治网络抖动、临时502、DNS超时这类“再试一次就好”的问题。它把重试逻辑从业务代码里剥离开,还能控制退避策略、停止条件和异常类型。
常见错误现象:requests.exceptions.ConnectionError、requests.exceptions.Timeout、HTTP 5xx 响应码反复出现,但手动重跑脚本又成功了——这就是典型该交给tenacity处理的场景。
- 只重试特定异常:用
retry_if_exception_type限定只对ConnectionError或Timeout重试,避免把404或401也重试一遍 - 别无脑固定间隔:用
wait_exponential实现指数退避,比如第一次等1s,第二次2s,第三次4s,防雪崩 - 设上限:用
stop_after_attempt(3)或stop_after_delay(10),防止卡死在无限重试里
怎么让tenacity适配requests.get这种函数?装饰器最轻量
不用改原有请求逻辑,给函数加个@retry就行。关键点是:装饰器必须作用在**独立函数**上,不能直接套在requests.get(...)调用表达式上。
使用场景:封装一个fetch_user_data函数,内部调用requests.get,然后对这个函数整体加重试。
立即学习“Python免费学习笔记(深入)”;
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import requests
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=1, max=10),
retry=retry_if_exception_type((
requests.exceptions.ConnectionError,
requests.exceptions.Timeout
))
)
def fetch_user_data(user_id):
return requests.get(f"https://api.example.com/users/{user_id}", timeout=5)
注意:timeout=5必须显式传给requests.get,否则tenacity无法捕获超时异常;max=10限制单次最长等待10秒,防止退避失控。
tenacity怎么判断HTTP状态码是否该重试?得自己写retry_if_result
默认tenacity只看异常,不看HTTP响应体。遇到返回200但{"code": 500, "msg": "服务暂时不可用"}这种“假成功”,就得靠retry_if_result或retry_if_exception钩子。
参数差异:retry_if_result接收函数返回值(即Response对象),你得在里面写判断逻辑;retry_if_exception则用于捕获并检查异常内容(比如JSONDecodeError)。
- 检查状态码:用
lambda r: r.status_code in (502, 503, 504) - 检查JSON结构:先
r.json()再判断data.get("code") == 500,但要包住ValueError防止解析失败 - 别漏掉
r.raise_for_status():它会把4xx/5xx转成HTTPError,方便统一进异常重试流
并发请求下用tenacity要注意什么?别让重试放大QPS
性能影响很实在:10个协程同时请求,每个最多重试3次,实际可能发出30次请求。如果目标接口限流严格,这等于主动触发限频。
容易踩的坑:
- 异步环境别混用同步装饰器:用
tenacity.AsyncRetrying替代@retry,否则await会被阻塞 - 共享连接池时,重试可能复用已断开的
httpx.AsyncClient连接,得配合client.aclose()或用limits=None避免连接耗尽 - 日志里务必打上
attempt_number:用before=before_log(...),否则线上出问题根本分不清是第几次重试挂的
复杂点在于:重试不是越猛越好,得跟下游服务的容错能力对齐。比如对方明确写了“503时请等待1秒后重试”,那就别用指数退避,老老实实用wait_fixed(1)。细节对不上,重试就从救急变成添乱。










