Python发送HTTP请求及超时重试技巧
时间:2025-06-24 10:38:19 182浏览 收藏
积累知识,胜过积蓄金银!毕竟在文章开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《Python发送HTTP请求及超时重试方法》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
要自定义重试策略,可使用urllib3.util.retry.Retry或自定义HTTPAdapter。1. 使用Retry设置总重试次数、退避因子、需重试的状态码及允许重试的请求方法;2. 通过自定义HTTPAdapter实现更灵活逻辑,如根据响应头或指数退避调整重试间隔;3. 还可创建完全自定义的重试类以获得最大灵活性。此外,Python中发送HTTP请求还可选择urllib3(底层灵活但API复杂)、aiohttp(异步高并发但学习曲线陡)、httpx(同步异步兼支持且功能强但生态较新)。处理HTTP状态码时可用response.raise_for_status()自动抛出异常,并结合try...except捕获不同错误,也可直接检查response.status_code属性执行特定处理逻辑。发送请求时设置代理可通过proxies参数指定各协议代理地址,HTTPS请求SSL验证默认开启,可设verify=False临时禁用(不推荐),最佳实践是将证书路径传给verify参数以保障安全。

在Python中发送HTTP请求,你需要借助一些库,比如requests。处理请求超时和重试,关键在于设置合适的参数和编写异常处理逻辑。

import requests
from requests.exceptions import Timeout, ConnectionError
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
def send_http_request(url, params=None, data=None, headers=None, timeout=5, max_retries=3):
"""
发送HTTP请求,并处理超时和重试。
Args:
url (str): 请求的URL。
params (dict, optional): URL参数。Defaults to None.
data (dict, optional): 请求体数据。Defaults to None.
headers (dict, optional): 请求头。Defaults to None.
timeout (int, optional): 超时时间(秒)。Defaults to 5.
max_retries (int, optional): 最大重试次数。Defaults to 3.
Returns:
requests.Response: 响应对象,如果所有重试都失败,则返回None。
"""
retry_strategy = Retry(
total=max_retries,
backoff_factor=1, # 重试间隔时间,单位秒,计算方式:{backoff factor} * (2 ** ({number of total retries} - 1))
status_forcelist=[429, 500, 502, 503, 504], # 哪些状态码需要重试
method_whitelist=["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE", "POST"] # 哪些请求方法允许重试
)
adapter = HTTPAdapter(max_retries=retry_strategy)
http = requests.Session()
http.mount("https://", adapter)
http.mount("http://", adapter)
try:
response = http.request(
"POST" if data else "GET", # 根据是否有data来决定请求方式,这是一个简化
url,
params=params,
data=data,
headers=headers,
timeout=timeout
)
response.raise_for_status() # 检查响应状态码,如果不是200,抛出异常
return response
except Timeout:
print(f"请求超时: {url}")
return None
except ConnectionError:
print(f"连接错误: {url}")
return None
except requests.exceptions.HTTPError as e:
print(f"HTTP错误: {e}")
return None
except Exception as e:
print(f"发生未知错误: {e}")
return None
# 示例用法
if __name__ == '__main__':
url = "https://www.example.com"
response = send_http_request(url, timeout=2, max_retries=2)
if response:
print(f"请求成功,状态码: {response.status_code}")
# print(f"响应内容: {response.text}")
else:
print("请求失败")如何自定义重试策略?
除了使用urllib3.util.retry.Retry,你还可以通过自定义requests.adapters.HTTPAdapter来实现更灵活的重试策略。例如,你可以根据响应头中的信息来决定是否重试,或者使用指数退避算法来调整重试间隔。你甚至可以完全自定义一个重试类,实现自己的重试逻辑。这需要你深入理解requests库的内部机制,但可以提供最大的灵活性。

import time
import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError, Timeout
class CustomRetry(HTTPAdapter):
def __init__(self, *args, **kwargs):
self.max_retries = kwargs.pop('max_retries', 3)
self.backoff_factor = kwargs.pop('backoff_factor', 0.5)
super(CustomRetry, self).__init__(*args, **kwargs)
def send(self, request, **kwargs):
retries = 0
while True:
try:
response = super(CustomRetry, self).send(request, **kwargs)
response.raise_for_status() # 检查状态码
return response
except (ConnectionError, Timeout) as e:
print(f"请求失败,正在重试 ({retries+1}/{self.max_retries}): {e}")
if retries >= self.max_retries:
raise # 达到最大重试次数,抛出异常
retries += 1
time.sleep(self.backoff_factor * (2 ** (retries - 1))) # 指数退避
except requests.exceptions.HTTPError as e:
# 这里可以根据状态码判断是否重试,例如只重试500错误
if e.response.status_code == 500 and retries < self.max_retries:
print(f"服务器错误,正在重试 ({retries+1}/{self.max_retries}): {e}")
retries += 1
time.sleep(self.backoff_factor * (2 ** (retries - 1)))
else:
raise # 不重试,抛出异常
def close(self):
super(CustomRetry, self).close()
if __name__ == '__main__':
session = requests.Session()
retry_adapter = CustomRetry(max_retries=3, backoff_factor=0.5)
session.mount('http://', retry_adapter)
session.mount('https://', retry_adapter)
try:
response = session.get('https://www.example.com', timeout=5)
print(f"请求成功,状态码: {response.status_code}")
except Exception as e:
print(f"请求失败: {e}")除了requests库,还有其他选择吗?它们有什么优缺点?
当然,除了requests,Python中还有其他发送HTTP请求的库,例如urllib3(requests的底层库)、aiohttp(用于异步请求)和httpx(支持同步和异步请求)。
urllib3: 优点是底层、灵活,适合构建更高级的HTTP客户端。缺点是API相对复杂,需要手动处理很多细节。aiohttp: 优点是基于asyncio,适合高并发的异步请求。缺点是学习曲线较陡峭,需要理解async/await的概念。httpx: 优点是同时支持同步和异步请求,API设计更现代化,功能更强大。缺点是相对较新,生态不如requests成熟。
选择哪个库取决于你的具体需求。如果只是简单的HTTP请求,requests通常是最佳选择。如果需要处理大量并发请求,可以考虑aiohttp或httpx。如果需要对HTTP协议进行更底层的控制,urllib3可能更适合。

如何处理不同的HTTP响应状态码?
处理HTTP响应状态码是构建健壮的HTTP客户端的关键。requests库提供了一个方便的方法response.raise_for_status(),它可以自动检查响应状态码,并在状态码表示错误时抛出异常。你可以在try...except块中使用它来捕获和处理错误。
但是,有时候你需要根据不同的状态码采取不同的处理方式。例如,你可能希望在收到404错误时记录日志,或者在收到503错误时进行重试。这时,你可以直接检查response.status_code属性,并根据它的值来执行不同的逻辑。
import requests
def handle_response(response):
if response.status_code == 200:
print("请求成功")
# 处理响应数据
elif response.status_code == 404:
print("资源未找到")
# 记录日志或采取其他措施
elif response.status_code == 503:
print("服务不可用,稍后重试")
# 实施重试策略
else:
print(f"发生未知错误: {response.status_code}")
response.raise_for_status() # 如果是不期望的状态码,仍然抛出异常如何在发送请求时设置代理?
在某些情况下,你可能需要通过代理服务器发送HTTP请求。requests库允许你通过proxies参数来设置代理。你可以为不同的协议(例如HTTP和HTTPS)设置不同的代理。
import requests
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
try:
response = requests.get("https://www.example.com", proxies=proxies, timeout=5)
response.raise_for_status()
print("请求成功")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")请注意,代理服务器可能会影响请求的性能和安全性。确保你使用的代理是可信的,并且配置正确。此外,一些代理服务器可能需要身份验证。你可以在代理URL中包含用户名和密码,例如http://user:password@10.10.1.10:3128。
如何处理HTTPS请求的SSL证书验证?
默认情况下,requests库会验证HTTPS请求的SSL证书,以确保连接的安全性。如果服务器的证书无效或过期,requests会抛出异常。
在某些情况下,你可能需要禁用SSL证书验证。例如,你可能正在连接到一个使用自签名证书的开发服务器。你可以通过设置verify=False来禁用证书验证。但是,这会降低连接的安全性,因此应该谨慎使用。
import requests
try:
response = requests.get("https://self-signed.example.com", verify=False, timeout=5)
response.raise_for_status()
print("请求成功")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")更好的做法是,将服务器的证书添加到你的信任列表中。你可以通过设置verify参数为证书文件的路径来实现。
import requests
try:
response = requests.get("https://example.com", verify="/path/to/certfile.pem", timeout=5)
response.raise_for_status()
print("请求成功")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")这可以确保连接的安全性,同时避免验证错误。
到这里,我们也就讲完了《Python发送HTTP请求及超时重试技巧》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于Http请求,超时重试的知识点!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
313 收藏
-
107 收藏
-
240 收藏
-
320 收藏
-
118 收藏
-
329 收藏
-
267 收藏
-
373 收藏
-
315 收藏
-
365 收藏
-
492 收藏
-
477 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习