Python中关于requests库timeout参数的疑问与使用详解
仔细看了下 requests 的官方文档,其中特别注明
“timeout 仅对连接过程有效,与响应体的下载无关。 timeout 并不是整个下载响应的时间限制,而是如果服务器在 timeout 秒内没有应答,将会引发一个异常(更精确地说,是在 timeout 秒内没有从基础套接字上接收到任何字节的数据时)”
现在遇到一个网站,响应时间非常快,但是"响应体的下载"非常慢,估计是防封策略故意设置的,这样我该如何应对呢?求老司机.
Python中关于requests库timeout参数的疑问与使用详解
比如你抓取某台国内机器的资源,因为是在国内,所以建立连接很快,但它带宽只有 1M ,所以下载响应体很慢。
帖子回复:
关于 requests 库的 timeout 参数,核心就两点:连接超时和读取超时。这俩是分开控制的,但用一个参数就能搞定。
1. 基本用法
import requests
# 设置总超时(连接+读取)为5秒
response = requests.get('https://api.example.com', timeout=5)
# 分别设置连接超时2秒,读取超时10秒
response = requests.get('https://api.example.com', timeout=(2, 10))
2. 关键细节
- 连接超时:从发请求到建立连接的时间,包括DNS解析、TCP握手、SSL握手
- 读取超时:连接建立后,等待服务器返回第一个字节的时间
- 超时异常:连接超时抛
ConnectTimeout,读取超时抛ReadTimeout - 默认行为:不设置timeout时,requests会一直等待(生产环境千万别这样!)
3. 实际场景示例
import requests
from requests.exceptions import Timeout, ConnectionError
try:
# 对慢速API:快速失败连接,但允许较长的读取时间
response = requests.get('https://slow-api.com/data', timeout=(3, 30))
print("请求成功")
except Timeout as e:
if isinstance(e, requests.exceptions.ConnectTimeout):
print("连接超时 - 服务器太慢或网络有问题")
elif isinstance(e, requests.exceptions.ReadTimeout):
print("读取超时 - 服务器处理请求太慢")
except ConnectionError:
print("连接错误 - 检查网络或URL")
4. 最佳实践
- 永远设置timeout:生产代码必须设置,防止线程/进程被卡死
- 区分内外网:内网服务可以用(2, 5),外网API建议(3, 10)
- 文件上传下载:读取超时要设长点,比如
timeout=(5, 60) - Session复用:给Session对象设置默认timeout
session = requests.Session()
session.request = functools.partial(session.request, timeout=(3, 10))
总结:timeout就是你的安全绳,不系就别爬高。
request 支持 stream 的方式,自己分片读,然后判断是否超时
现在就是响应体下载很慢,想设置一个超时,应该怎么做呢?
如果我想设置一个针对响应体的超时怎么办呢?
http://docs.python-requests.org/en/master/user/advanced/#streaming-requests
started_time = time.time()
timeout = 60
r = requests.get(‘http://httpbin.org/stream/20’, stream=True)
if r.encoding is None:
r.encoding = 'utf-8’
for line in r.iter_lines(decode_unicode=True):
if time.time() - started_time > 60:
print “timeout”
break
if line:
print json.loads(line)
感谢~~~,难为了我一下午的问题貌似有着落了,ORZ
timeout 可以设置 tuple 的, http://docs.python-requests.org/en/master/api/
看文档啊,少年。
这个路子好野。 60 是拍脑袋出来的? 万一 10s 服务端就把连接关了呢。
这个只是举个例子可以这样玩
要是服务器端关闭了,这个迭代器应该是会抛出异常的
但实际上它并不会抛出异常,至少我断网了 10 分钟还是正常的

