Python requests 超时与重试入门

举报
yd_259811995 发表于 2026/11/05 06:15:34 2026/11/05
【摘要】 刚开始用 Python 写网络请求时,很多人只关心能不能拿到数据,却容易忽略两个最常见的翻车点:请求一直卡住,以及偶发失败后直接报错退出。requests 库本身提供了超时和重试的机制,理解它们的分工,就能让脚本在真实网络里稳得多。 超时不是一个数字requests 的 timeout 参数看起来简单,实际上包含两个阶段。连接超时是指建立 TCP 连接的最长等待时间,读取超时是指发送请求后等...

刚开始用 Python 写网络请求时,很多人只关心能不能拿到数据,却容易忽略两个最常见的翻车点:请求一直卡住,以及偶发失败后直接报错退出。requests 库本身提供了超时和重试的机制,理解它们的分工,就能让脚本在真实网络里稳得多。

超时不是一个数字

requests 的 timeout 参数看起来简单,实际上包含两个阶段。连接超时是指建立 TCP 连接的最长等待时间,读取超时是指发送请求后等待服务器返回数据的最长等待时间。写成 timeout=5 时,两个阶段各最多等 5 秒;写成元组 timeout=(3, 10) 时,连接最多等 3 秒,读取最多等 10 秒。

只给一个很大的总时间并不保险。连接阶段卡住和读取阶段缓慢是两种不同的故障,前者往往是网络或地址问题,后者可能是服务端处理太慢。分开设置的好处是定位更快:连接超时多半要检查地址、代理和网络,读取超时则要看接口本身是不是太重,或者是不是需要分页、降级。

没有超时会发生什么

不传 timeout 时,请求可能一直等下去。对一次性脚本来说只是多等一会儿,对定时任务和批量抓取来说就很危险:一个卡住的请求会拖住整个队列,后面的任务全部排队,严重时还会把连接池占满。因此我的习惯是:所有发往外部的请求都必须显式传 timeout,哪怕只是先给一个保守值,后面再根据接口表现调优。

重试要解决偶发失败

超时、连接重置、服务端短暂返回 502 或 503,很多都属于偶发问题,稍后再试一次往往就好了。重试的核心不是无脑循环,而是三条规则。第一,只对可重试的失败重试,例如超时和 5xx,客户端参数写错导致的 4xx 不应该反复重试。第二,次数要有限,一般 2 到 3 次就够了,太多只会放大服务端压力。第三,两次重试之间要留间隔,最好带一点随机抖动,避免大量客户端在同一秒一起重试。

一个可直接用的写法

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

retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session = requests.Session()
session.mount('https://', adapter)
resp = session.get('https://example.com/api', timeout=(3, 10))
resp.raise_for_status()
print(resp.status_code)

这里 backoff_factor 会让等待时间逐步拉长,配合 status_forcelist 只对指定的服务端错误重试。注意,默认情况下重试主要针对连接类错误和指定状态码,读取超时等失败是否重试,要结合接口是否幂等来判断。

幂等与副作用

重试最容易踩的坑是重复提交。查询类请求重试一般是安全的,但下单、扣款、创建资源这类有副作用的操作,重复发一次可能就多产生一条记录。遇到这类接口,优先用接口提供的幂等键,或者先查询结果再决定是否补发,而不是直接循环重试。

上线前的检查清单

第一,所有请求都有 timeout,而且连接和读取分开考虑。第二,重试次数有限,间隔带抖动,只重试偶发失败。第三,日志里记录超时类型、状态码和重试次数,方便区分是网络问题还是服务端问题。第四,批量任务要控制并发,避免重试把本已吃紧的服务端彻底压垮。

把超时和重试当成默认配置而不是事后补丁,脚本的健壮性会立刻上一个台阶。下次写 requests 代码时,先问自己一句:这个请求卡住了怎么办,失败了要不要再试一次,答案写进代码里,比事后排查省事得多。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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