登录
首页 >  文章 >  python教程

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请求?如何处理请求超时和重试?

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

Python中如何发送HTTP请求?如何处理请求超时和重试?
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库的内部机制,但可以提供最大的灵活性。

Python中如何发送HTTP请求?如何处理请求超时和重试?
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请求的库,例如urllib3requests的底层库)、aiohttp(用于异步请求)和httpx(支持同步和异步请求)。

  • urllib3: 优点是底层、灵活,适合构建更高级的HTTP客户端。缺点是API相对复杂,需要手动处理很多细节。
  • aiohttp: 优点是基于asyncio,适合高并发的异步请求。缺点是学习曲线较陡峭,需要理解async/await的概念。
  • httpx: 优点是同时支持同步和异步请求,API设计更现代化,功能更强大。缺点是相对较新,生态不如requests成熟。

选择哪个库取决于你的具体需求。如果只是简单的HTTP请求,requests通常是最佳选择。如果需要处理大量并发请求,可以考虑aiohttphttpx。如果需要对HTTP协议进行更底层的控制,urllib3可能更适合。

Python中如何发送HTTP请求?如何处理请求超时和重试?

如何处理不同的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请求,超时重试的知识点!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>