pin_drop当前位置:知识文库 ❯ 图文
requests超时设置详解 - 连接超时、读取超时与重试机制
一、概述
在网络请求中,超时设置是保障程序健壮性的关键机制。requests库通过timeout参数控制请求的最长等待时间,防止因网络延迟或服务器无响应导致程序长时间阻塞。
合理设置超时时间可以避免资源浪费,提升程序的容错能力。在生产环境中,不设置超时是一个非常常见的错误,可能导致程序永久挂起,消耗系统资源并影响用户体验。
二、超时参数说明
基本语法
代码示例
import requests
# 方式1:设置统一的超时时间(连接+读取)
requests.get(url, timeout=5)
# 方式2:分别设置连接超时和读取超时
requests.get(url, timeout=(3, 10)) # (连接超时, 读取超时)参数详解
三、超时类型与异常
超时类型说明
四、代码示例
示例1:基本超时设置
代码示例
import requests
# 设置5秒超时(连接和读取各5秒)
try:
response = requests.get('https://httpbin.org/delay/1', timeout=5)
print(f"请求成功,状态码: {response.status_code}")
except requests.exceptions.Timeout:
print("请求超时")
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
代码示例
import requests
# 设置5秒超时(连接和读取各5秒)
try:
response = requests.get('https://httpbin.org/delay/1', timeout=5)
print(f"请求成功,状态码: {response.status_code}")
except requests.exceptions.Timeout:
print("请求超时")
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")输出:
代码示例
请求成功,状态码: 200示例2:分别设置连接超时和读取超时
代码示例
import requests
# 连接超时3秒,读取超时10秒
timeout_config = (3, 10)
try:
# 请求延迟2秒的接口(读取超时10秒内可完成)
response = requests.get('https://httpbin.org/delay/2', timeout=timeout_config)
print(f"延迟2秒请求成功: {response.status_code}")
except requests.exceptions.ConnectTimeout:
print("连接超时")
except requests.exceptions.ReadTimeout:
print("读取超时")
# 测试读取超时
try:
# 请求延迟15秒的接口(超过读取超时10秒)
response = requests.get('https://httpbin.org/delay/15', timeout=timeout_config)
print(f"延迟15秒请求成功: {response.status_code}")
except requests.exceptions.ReadTimeout:
print("读取超时:服务器响应时间过长")输出:
代码示例
延迟2秒请求成功: 200
读取超时:服务器响应时间过长示例3:超时重试机制
代码示例
import requests
import time
def request_with_retry(url, max_retries=3, timeout=5):
"""带重试机制的请求函数"""
for attempt in range(1, max_retries + 1):
try:
response = requests.get(url, timeout=timeout)
print(f"第{attempt}次请求成功: {response.status_code}")
return response
except requests.exceptions.Timeout:
print(f"第{attempt}次请求超时,等待{attempt}秒后重试...")
time.sleep(attempt)
except requests.exceptions.ConnectionError:
print(f"第{attempt}次连接失败,等待{attempt}秒后重试...")
time.sleep(attempt)
except requests.exceptions.RequestException as e:
print(f"第{attempt}次请求异常: {e}")
time.sleep(attempt)
print(f"已重试{max_retries}次,请求失败")
return None
# 测试重试机制
result = request_with_retry('https://httpbin.org/delay/1', max_retries=3, timeout=5)输出:
代码示例
第1次请求成功: 200五、实际应用场景
-
场景1:爬虫程序超时控制:为每个请求设置超时,避免因单个页面无响应导致整个爬虫阻塞。配合重试机制,可以有效应对网络波动和服务器临时故障。
-
场景2:微服务超时与熔断:在微服务调用中,设置合理的超时时间,配合熔断器(如Hystrix、resilient-python)实现故障快速恢复,避免级联故障。
-
场景3:批量API调用优化:批量调用多个API时,设置较短超时,快速跳过无响应的服务,继续处理后续任务,提高整体处理效率。
六、注意事项
注意1:timeout默认为None(永不超时),生产环境中必须设置超时,否则可能导致程序永久阻塞,消耗系统资源。
注意2:timeout不是整个请求的总时间限制,而是等待连接建立或等待数据读取的时间。一个请求的总耗时可能远超timeout值(如重试、重定向等情况)。
注意3:超时时间设置过短可能导致正常请求被误判为超时,建议根据网络环境和服务器响应时间合理设置。可以先用较大超时值测试,再逐步调优。
七、超时异常层级对比
requests库提供了多个超时相关的异常类,了解它们的继承关系有助于编写更精确的异常处理代码:
小贴士
异常继承关系:RequestException → Timeout → ConnectTimeout/ReadTimeout。如果只想捕获所有超时情况,使用except requests.exceptions.Timeout即可;如果需要区分连接超时和读取超时,分别捕获ConnectTimeout和ReadTimeout。
八、小结
-
timeout参数控制请求的最长等待时间,防止程序无限阻塞。 -
元组形式
(连接超时, 读取超时)可以分别控制两种超时,提供更精细的控制。 -
生产环境必须设置超时,推荐连接超时3-5秒,读取超时10-30秒。
-
超时后应配合重试机制,提升请求的可靠性。
九、练习题
练习1
编写程序,请求 https://httpbin.org/delay/5,分别设置timeout=3和timeout=10,观察超时行为的差异。
练习2
编写程序,使用元组形式设置连接超时2秒、读取超时5秒,并分别捕获ConnectTimeout和ReadTimeout异常。
练习3
编写一个带指数退避重试的请求函数,超时后等待时间依次为1秒、2秒、4秒,最多重试3次。
常见问题
1. 超时时间设置多少合适?
这取决于具体场景。一般建议:连接超时3-5秒(TCP连接通常很快),读取超时10-30秒(取决于服务器处理速度)。对于已知响应较慢的接口(如大数据查询),可适当延长读取超时到60秒。可以先用较大值测试,再根据实际响应时间逐步调优。
2. timeout=0表示什么?
timeout=0表示立即超时,几乎任何请求都会触发超时异常。这通常用于测试目的,验证超时处理逻辑是否正确。实际应用中不应该使用timeout=0。
3. 如何为Session设置全局超时?
Session本身没有直接的全局超时设置。但可以通过自定义HTTPAdapter来设置:session.mount('https://', requests.adapters.HTTPAdapter(max_retries=3)),或者在每个请求中单独设置timeout。也可以使用requests-toolbelt库提供的超时适配器。
4. 超时和重试应该如何配合?
超时后重试时,建议逐步增加等待时间(指数退避),避免瞬间大量重试给服务器造成压力。例如第一次等待1秒,第二次等待2秒,第三次等待4秒。同时设置最大重试次数,避免无限重试。可以使用urllib3.util.Retry来简化重试逻辑。
5. 超时会影响下载大文件吗?
会的。读取超时是从服务器接收数据的超时时间,如果下载大文件时读取速度较慢,可能会触发读取超时。对于大文件下载,建议设置较大的读取超时,或者使用stream=True配合iter_content()分块下载,并在每次读取chunk时单独处理超时。
本文涉及AI创作
内容由AI创作,请仔细甄别