《Python requests 超时设置与重试:别让一次网络抖动拖垮程序》

举报
yd_278701352 发表于 2026/11/02 00:33:45 2026/11/02
【摘要】 用 Python 写过爬虫、调用过第三方 API 的人,大概率都踩过同一个坑:程序平时跑得好好的,某天突然卡住不动,也没有报错,日志停在某一次请求上。十有八九,这就是请求没有设超时。requests 库的默认行为是「一直等下去」。requests.get(url) 不传 timeout,遇到服务端迟迟不响应、网络半断不断的情况,程序就会无限期挂起。线上服务里,这意味着一个线程被占住;爬虫里,...

用 Python 写过爬虫、调用过第三方 API 的人,大概率都踩过同一个坑:程序平时跑得好好的,某天突然卡住不动,也没有报错,日志停在某一次请求上。十有八九,这就是请求没有设超时。

requests 库的默认行为是「一直等下去」。requests.get(url) 不传 timeout,遇到服务端迟迟不响应、网络半断不断的情况,程序就会无限期挂起。线上服务里,这意味着一个线程被占住;爬虫里,意味着整个队列停摆。所以第一条铁律是:每一次 requests 调用都必须传 timeout。

timeout 可以传一个数字,也可以传一个元组。timeout=5 表示连接和读取总共最多等 5 秒;timeout=(3, 10) 则分开控制:3 秒内连不上就放弃,连上之后 10 秒内读不到数据也放弃。推荐用元组写法,因为「连不上」和「对方处理慢」是两种不同的问题,分开设限更容易定位。内网服务可以设得宽松一点,比如 (3, 30);公网第三方接口建议收紧,比如 (3, 10),慢接口宁可快速失败,也不要拖垮自己的服务。

设了超时,程序就不会再卡死,但会抛出异常。常见的有两种:ConnectTimeout(连不上)和 ReadTimeout(连上了但对方迟迟不回数据),它们都是 requests.exceptions.Timeout 的子类。处理时不要只写一个笼统的 except 把异常吞掉,至少要区分超时、连接错误和 HTTP 状态错误,日志里把 URL 和耗时记下来,否则出问题时根本无从查起。

光有超时还不够。网络抖动是常态:对方服务重启、中间节点丢包、DNS 偶尔抽风,一次失败不代表真的不可用。这时候需要重试,但重试要讲策略。最简单的办法是用 urllib3 的 Retry 挂到 HTTPAdapter 上:

from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import requests

retry = Retry(total=3, backoff_factor=1, status_forcelist=[502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session = requests.Session()
session.mount("https://", adapter)
session.mount("http://", adapter)

resp = session.get("https://example.com/api", timeout=(3, 10))

这里有三个要点。第一,total=3 是总重试次数,不是无限重试;第二,backoff_factor=1 会让等待时间按 0 秒、2 秒、4 秒递增,避免在对方已经过载时继续猛攻;第三,status_forcelist 只对 502、503、504 这类「服务端临时故障」重试,404、400 这种客户端问题重试多少次都没用,不应列入。

还有一个容易被忽略的原则:只有幂等的请求才适合自动重试。GET、HEAD 这类只读请求重试是安全的;POST 下单、扣款、创建资源这类操作,重试可能导致重复执行,必须先确认接口支持幂等键,或者改由业务层人工处理。把重试无脑套在所有请求上,是比不重试更危险的做法。

最后说说日志和监控。超时和重试本身不是故障,偶发一两次完全正常;但如果某个接口的超时率突然从千分之一涨到百分之几,那往往是对方服务或网络链路出了问题。把每次超时、重试的 URL、耗时和最终结果记下来,定期看一眼,比事后翻日志救火要轻松得多。

总结一下:每次请求都设 timeout,连接和读取分开设;超时异常要分类捕获、记日志;重试只给幂等请求、次数有限、带退避间隔;502、503、504 才值得重试。这四条做到了,一次网络抖动就只是一条日志,而不是一次线上事故。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。