---
title: "如何有效使用 Python Requests 重试机制"
description: "学习如何结合退避策略、代理与自定义逻辑使用 Python requests 重试机制，从而处理 HTTP 错误并避免被封锁。"
url: "https://marsproxies.cn/blog/python-requests-retry/"
---

[跳到主要内容](https://marsproxies.cn/blog/python-requests-retry/#page-content)

- [英语](https://marsproxies.com/blog/python-requests-retry/)
- [中文](https://marsproxies.cn/blog/python-requests-retry/)

[联系销售](https://marsproxies.cn/contact-sales/) [登录](https://dashboard.marsproxies.com/login/)

[注册](https://dashboard.marsproxies.com/register/)

[联系销售](https://marsproxies.cn/contact-sales/) [登录](https://dashboard.marsproxies.com/login/)

- [英语](https://marsproxies.com/blog/python-requests-retry/)
- [中文](https://marsproxies.cn/blog/python-requests-retry/)

[返回博客](https://marsproxies.cn/blog/) 2025年8月20日

# 如何有效使用 Python Requests 重试机制

[操作指南](https://marsproxies.cn/blog/category/how-to/)

\-

目录

1. [请求失败的常见原因](https://marsproxies.cn/blog/python-requests-retry/#b-%E8%AF%B7%E6%B1%82%E5%A4%B1%E8%B4%A5%E7%9A%84%E5%B8%B8%E8%A7%81%E5%8E%9F%E5%9B%A0)
2. [使用 HTTPAdapter 重试 Python 请求](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BD%BF%E7%94%A8-httpadapter-%E9%87%8D%E8%AF%95-python-%E8%AF%B7%E6%B1%82)
3. [How built-in retries work in requests](https://marsproxies.cn/blog/python-requests-retry/#b-how-built-in-retries-work-in-requests)
4. [示例：使用 Retry 配置 HTTPAdapter](https://marsproxies.cn/blog/python-requests-retry/#b-%E7%A4%BA%E4%BE%8B%E4%BD%BF%E7%94%A8-retry-%E9%85%8D%E7%BD%AE-httpadapter)
5. [需要调整的关键参数](https://marsproxies.cn/blog/python-requests-retry/#b-%E9%9C%80%E8%A6%81%E8%B0%83%E6%95%B4%E7%9A%84%E5%85%B3%E9%94%AE%E5%8F%82%E6%95%B0)
6. [自定义重试逻辑与装饰器](https://marsproxies.cn/blog/python-requests-retry/#b-%E8%87%AA%E5%AE%9A%E4%B9%89%E9%87%8D%E8%AF%95%E9%80%BB%E8%BE%91%E4%B8%8E%E8%A3%85%E9%A5%B0%E5%99%A8)
7. [基于 Try/Except 的重试循环](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%9F%BA%E4%BA%8E-tryexcept-%E7%9A%84%E9%87%8D%E8%AF%95%E5%BE%AA%E7%8E%AF)
8. [带抖动的指数退避](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%B8%A6%E6%8A%96%E5%8A%A8%E7%9A%84%E6%8C%87%E6%95%B0%E9%80%80%E9%81%BF)
9. [使用 tenacity 库实现重试](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BD%BF%E7%94%A8-tenacity-%E5%BA%93%E5%AE%9E%E7%8E%B0%E9%87%8D%E8%AF%95)
10. [何时应优先选用自定义逻辑而非 HTTPAdapter](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BD%95%E6%97%B6%E5%BA%94%E4%BC%98%E5%85%88%E9%80%89%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%BB%E8%BE%91%E8%80%8C%E9%9D%9E-httpadapter)
11. [处理 429 和 503 等 HTTP 状态码](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%A4%84%E7%90%86-429-%E5%92%8C-503-%E7%AD%89-http-%E7%8A%B6%E6%80%81%E7%A0%81)
12. [结合代理与反封锁策略重试 Python 请求](https://marsproxies.cn/blog/python-requests-retry/#b-%E7%BB%93%E5%90%88%E4%BB%A3%E7%90%86%E4%B8%8E%E5%8F%8D%E5%B0%81%E9%94%81%E7%AD%96%E7%95%A5%E9%87%8D%E8%AF%95-python-%E8%AF%B7%E6%B1%82)
13. [为什么代理对重试请求很重要](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BB%A3%E7%90%86%E5%AF%B9%E9%87%8D%E8%AF%95%E8%AF%B7%E6%B1%82%E5%BE%88%E9%87%8D%E8%A6%81)
14. [在使用代理时调整重试逻辑](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%9C%A8%E4%BD%BF%E7%94%A8%E4%BB%A3%E7%90%86%E6%97%B6%E8%B0%83%E6%95%B4%E9%87%8D%E8%AF%95%E9%80%BB%E8%BE%91)
15. [实现基本的代理轮换](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%AE%9E%E7%8E%B0%E5%9F%BA%E6%9C%AC%E7%9A%84%E4%BB%A3%E7%90%86%E8%BD%AE%E6%8D%A2)
16. [代理管理相关的库与工具](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BB%A3%E7%90%86%E7%AE%A1%E7%90%86%E7%9B%B8%E5%85%B3%E7%9A%84%E5%BA%93%E4%B8%8E%E5%B7%A5%E5%85%B7)
17. [重试请求的最佳实践](https://marsproxies.cn/blog/python-requests-retry/#b-%E9%87%8D%E8%AF%95%E8%AF%B7%E6%B1%82%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5)
18. [结论](https://marsproxies.cn/blog/python-requests-retry/#b-%E7%BB%93%E8%AE%BA)

\-

现代 Web API 和数据抓取项目经常会遇到 HTTP 请求失败的情况：服务器可能暂时宕机、网络可能出现短暂故障、目标网站也可能施加速率限制。

在这些情况下，让 Python 脚本自动重试失败的请求可以帮您化解问题。requests 库让在 Python 中发送 HTTP 请求变得简单，但它并不会神奇地消除超时或连接中断等错误。

在本指南中，我们将探讨如何有效使用 [Python requests](https://marsproxies.cn/blog/python-requests-timeout/) 的重试机制：从利用 requests 内置的功能，到编写带指数退避的自定义重试循环、处理特殊 HTTP 状态码、使用代理进行反封锁等。

## 请求失败的常见原因

在实现重试机制之前，先了解请求失败的根本原因非常重要。常见原因包括网络问题、服务器问题和客户端错误：

- 网络问题

临时的网络波动可能导致连接错误或超时。例如，网络连接不佳或 [DNS 问题](https://www.cloudflare.com/learning/dns/common-dns-issues/)可能导致请求根本无法到达服务器。

- 服务器端错误

5xx 范围（500-599）的 HTTP 状态码表示服务器在处理请求时遇到了错误。例如，500（内部服务器错误）或 502（错误网关）表明服务器端出现了问题。此类错误通常是暂时的，服务器可能会在短时间内恢复正常。

- 客户端错误与速率限制

4xx 的 HTTP 状态码通常表示请求本身存在问题。有些是永久性的，比如 404 Not Found 或 401 Unauthorized，除非您修改请求（纠正 URL 或凭据）才能解决。但也有一些属于临时性问题。

429 Too Many Requests 表示您已触及速率限制，服务器要求您放慢请求频率。类似地，403 Forbidden 可能是由于服务器屏蔽了您的访问（例如因为触发了反抓取防护）。

总之，只应对可能属于临时性的问题进行重试。网络波动、超时等异常以及 5xx 服务器错误都是适合重试的情况。而永久性错误（速率限制以外的 400 级别问题）通常不应该盲目重试。

理解失败的原因，有助于判断重试是否值得，还是需要采取其他修复方式（例如纠正错误的 URL 或补充正确的身份验证信息）。

## 使用 HTTPAdapter 重试 Python 请求

Python 的 *requests* 库默认不会重试失败的请求，但它提供了实现重试的工具。在底层，*requests* 使用 *urllib3* 这个 HTTP 客户端，其中包含一个处理重试逻辑的 *Retry* 类。

关键在于使用带有自定义 HTTPAdapter 的会话对象。HTTPAdapter 允许您配置一套重试策略，供该会话发出的所有请求使用。

### How built-in retries work in *requests*

开箱即用的 [*requests* 库](https://pypi.org/project/requests/)不会自动重试失败的请求（可能除了重定向请求这类少数特定场景）。这是有意为之的设计，重试行为被交由开发者自行决定。

好消息是，requests 允许您通过适配器机制接入一套 *Retry* 配置。*requests.adapters.HTTPAdapter* 可以通过 *max\_retries* 参数进行配置，该参数接受一个来自 *urllib3* 的 *Retry* 对象。将该适配器挂载到会话上后，即可为通过该会话发出的请求启用自动重试。

urllib3 的 *Retry* 类提供了灵活的重试行为：您可以指定允许的总重试次数、哪些 HTTP 状态码应触发重试、哪些请求方法应被重试，以及重试之间如何等待（例如使用退避算法）。

需要注意的是，*Retry* 逻辑只会应用于通过挂载了该适配器的会话发出的请求，不会影响 *requests.get()* 等其他未经过该会话的调用。

在接下来的部分中，我们将通过一个示例演示如何用 *Retry* 配置 *HTTPAdapter*，并讨论可以调整的关键设置，以实现有效的重试。

### 示例：使用 Retry 配置 HTTPAdapter

让我们搭建一个基础示例，使用 *requests* 内置的适配器机制自动重试失败的请求。我们将结合使用 HTTPAdapter 类（从 *requests.adapters* 导入 [*HTTPAdapter*](https://docs.nestjs.com/faq/http-adapter/)）与 urllib3 的 *Retry* 类：

```python
import requests
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
# Define a retry strategy
retry_strategy = Retry(
    total= 3 ,                   # total retry attempts (excluding the first request)
    backoff_factor= 1 ,          # factor for delay between retries
    status_forcelist= [ 429 , 500 , 502 , 503 , 504 ] ,  # HTTP codes to retry
    allowed_methods= [ "HEAD" , "GET" , "OPTIONS" ]   # methods to retry (None means any)
)

# Create an adapter with the retry strategy
adapter = HTTPAdapter(max_retries=retry_strategy)
# Create a session and mount the adapter to both HTTP and HTTPS
session = requests.Session( )
session.mount( "http://" , adapter)
session.mount( "https://" , adapter)

# Now use session to make requests
try :
    response = session.get( "https://httpbin.org/status/503" , timeout= 5 )
    print ( f"Final status:  {response.status_code} " )
except Exception as e:
    print ( f"Request failed:  {e} " )
```

在这段代码中，我们配置了一套重试策略，对于某些 HTTP 状态码，最多尝试三次重试（算上最初的请求，总共最多四次）。我们将 *status\_forcelist* 设置为 *\[429, 500, 502, 503, 504]*，这意味着出现这些状态码的响应都会被视为可重试。

设置 *backoff\_factor=1*会在重试之间强制加入延迟（我们稍后会解释退避计算方式）。我们把适配器挂载到会话对象上，然后使用 session.get 发出请求。

这样一来，如果目标 URL 返回 503 Service Unavailable，会话会自动重试请求，最多重试三次后才会放弃。

请注意，我们在 *get()* 调用中加入了 *timeout=5*。为请求设置超时是一种良好实践，尤其是在使用重试机制时，这样可以避免每次尝试无限期挂起。

### 需要调整的关键参数

在使用带 *Retry* 对象的 *HTTPAdapter* 时，有几个重要参数可以根据您的使用场景进行调整：

- 总重试次数

该参数控制总重试次数（不含最初的请求）。在我们的示例中，我们设置了 total=3，意味着请求失败后最多可以再尝试 3 次。将 total=None 设为不限次数（不建议这样做），将 total=0 则会完全禁用重试。

- 状态码筛选

参数 *status\_forcelist* 是一个应触发重试的 HTTP 状态码列表。默认情况下，除非您指定该列表，否则 urllib3 的 Retry 根本不会基于状态码进行重试。

- 允许重试的 HTTP 方法

默认情况下，只有被视为幂等的“安全”HTTP 方法（如 GET、HEAD、OPTIONS 以及 PUT/Delete）才会启用重试。这样做是为了避免重试非幂等请求（如 POST），因为重复提交表单或购买操作可能产生副作用。

- 退避设置

参数 *backoff\_factor* 是避免对服务器造成轰炸式请求的关键设置。该系数与重试次数相结合，决定了下一次尝试之前需要等待多久。

- 错误处理行为

默认情况下，一旦重试次数用尽，requests 会话会抛出异常（来自 urllib3 的 *MaxRetryError*，该异常会被封装进 *requests.exceptions.RetryError* 中）。

通过这些参数，您可以精细调整重试策略的行为。例如，您可能只想在连接错误时重试，而不在 HTTP 错误时重试，反之亦然——这可以通过调整 *Retry* 的设置来实现。对于许多场景，使用 HTTPAdapter 的内置方式都很方便，而且一旦配置完成，代码也能保持相对简洁。

## 自定义重试逻辑与装饰器

内置的适配器方式很实用，但有时您需要的自定义程度超出了它所能提供的范围。您可能希望添加日志记录、实现特殊的重试逻辑（比如在失败时刷新身份验证令牌），或处理一些 urllib3 的 Retry 无法覆盖的情况（例如根据成功响应的内容决定是否重试）。

在这类情况下，编写自己的重试循环或使用第三方库会是更合适的做法。下面我们来看几种实现方式。

### 基于 Try/Except 的重试循环

最简单的自定义重试形式，是使用带 try/except 代码块的循环。这让您能够完全控制要捕获哪些错误，以及如何响应。下面是重试逻辑循环的一个基本模式：

```python
import requests
import time
max_retries = 3
for attempt in range ( 1 , max_retries+ 1 ) :
    try :
        response = requests.get(url, timeout= 10 )
        # Check if response is successful
        if response.status_code == 200 :
            print ( "Success on attempt" , attempt)
            break  # exit loop on success
        else :
            print ( f"Received status  {response.status_code} ." )
            # Optionally, decide if this status should trigger a retry or not
    except requests.exceptions.Timeout as e:
        print ( "Request timed out, attempt" , attempt)
        # We can retry on timeouts
    except requests.exceptions.RequestException as e:
        print ( "Request failed:" , e)
        # Handle other exceptions (ConnectionError, etc.)
    # If we reach here, it means we need to retry
    if attempt < max_retries:
        time.sleep( 2 )  # wait 2 seconds before next attempt
    else :
        print ( "All retries failed." )
```

在这段代码中，我们最多尝试请求三次。我们显式捕获了超时异常（使用 *requests.exceptions.Timeout*），并将其视为可重试的情况。我们还捕获了一个通用的 *RequestException*，用于覆盖连接错误等其他问题。

每次失败之后，如果重试次数尚未用尽，我们会固定等待两秒再进行下一次尝试。

### 带抖动的指数退避

在实现自定义重试时，使用指数退避算法是一种推荐做法。与其在各次尝试之间固定等待一段时间，不如从一个较小的延迟开始，并在每次重试时按指数增长。这样可以减轻服务器的负担，避免大量重试请求同时涌入造成的“惊群效应”。

加入抖动意味着为这些延迟值加入一定的随机性。当多个客户端或线程同时重试时，抖动很有帮助，它能让各次重试的时间错开，避免所有请求再次同时访问服务器。

下面展示了如何生成一组带有可选抖动的退避延迟列表：

```python
import math, random
def make_backoff_delays (base_delay, factor, max_retries, jitter= False ) :
    delays = [ ]
    for n in range (max_retries) :
        # Exponential backoff: factor^(n) * base_delay
        delay = (factor ** n) * base_delay
        if jitter:
            # random jitter between 0.5x and 1.5x of delay
            delay = delay * random.uniform( 0.5 , 1.5 )
        delays.append(delay)
    return delays
# Example: 5 retries, base 1s, factor 2
print (make_backoff_delays(base_delay= 1 , factor= 2 , max_retries= 5 , jitter= True ) )
```

运行上述代码会输出类似 *\[1.2, 2.1, 4.3, 8.5, 16.2]*&#x7684;一组数值（由于存在随机性，具体数值会有所不同）。总体思路是：等待时间随着每次尝试逐渐变长。使用指数退避可以避免压垮服务器，这是一种被广泛推荐的做法，优于可能使服务器过载的固定延迟方式。

### 使用 tenacity 库实现重试

如果您不想从零开始编写重试循环，可以借助 *tenacity* 库，这是一个用于在 Python 中实现重试的强大第三方包。

要使用 *tenacity*，首先需要安装它（例如执行 *pip install tenacity*）。然后，您可以将它的 *@retry* 装饰器应用到执行请求的函数上。例如：

```python
from tenacity import retry, stop_after_attempt, wait_exponential
# Configure the retry decorator
@retry (stop=stop_after_attempt( 4 ) , wait=wait_exponential(multiplier= 1 , min = 2 , max = 10 ) )
def fetch_with_retry (url) :
    return requests.get(url, timeout= 5 )
```

在这段代码中，@*retry* 最多会将该函数重试四次（*stop\_after\_attempt(4)* 表示最多尝试四次），并在各次尝试之间使用指数等待。这里的 *wait\_exponential* 配置从两秒延迟开始，每次翻倍（重试之间的等待时间最多为 10 秒）。

### 何时应优先选用自定义逻辑而非 HTTPAdapter

在内置的 *HTTPAdapter* 重试机制和自定义方法（包括 tenacity）都可供选择的情况下，您可能会想该如何取舍。以下是一些需要考虑的因素：

- 复杂条件

如果需要根据复杂条件进行重试，例如前面讨论过的 200 OK 响应内容、或是在执行某种修复操作（比如刷新 OAuth 令牌）之后再重试，这时就需要用到自定义逻辑了。

- 每次尝试执行不同操作

有时您可能希望在每次重试时改变操作方式。例如，第二次失败后，可以切换到另一个 URL 或调整请求参数。

- 集成与日志记录

如果您需要在每次重试时进行详细的日志记录、指标采集，或与系统其他部分集成（比如记录每次尝试，或在失败 X 次后通知其他服务），自定义方案能为您提供这种控制能力。

- 特定异常处理

虽然 *urllib3 的* *Retry* 会自动处理一些底层异常（例如连接错误），但您可能仍希望显式处理其他异常。

- 运行环境

在某些环境中（例如异步框架，或使用 aiohttp 而非 requests 时），HTTPAdapter 方案并不适用。Tenacity 或手动重试逻辑可以针对这些场景做相应调整（例如使用异步等待）。

## 处理 429 和 503 等 HTTP 状态码

在重试场景中，某些 HTTP 状态码值得特别关注，其中两种常见的是 429 Too Many Requests 和 503 Service Unavailable：

- 429（请求过多）

该状态码表示服务器正在对您进行速率限制，也就是说您在短时间内发送了过多请求。许多服务器会在 429 响应中附带 Retry-After 请求头，告知您需要等待多少秒后再重试。

您的重试逻辑应检查这一点。例如，收到 429 响应时，查看 *response.headers.get("Retry-After")*；如果该字段存在且值为“30”，则应等待 30 秒后再进行下一次尝试。

- 503（服务不可用）

503 通常表示服务器暂时无法处理请求（服务器过载或正在维护）。与 429 类似，如果服务器预计稍后恢复可用，响应中也可能带有 Retry-After 请求头。此时应按照指定时长暂停重试。

对于 429 和 503（以及 502 Bad Gateway、504 Gateway Timeout 等类似错误），只要配合退避策略并遵循服务器的信号，重试就能发挥作用。务必避免对这些响应进行高频快速重试。使用 Retry-After 请求头是一种良好实践——如果服务器提示“60 秒后再试”，就应当遵循。

重试 Python 请求时轮换 IP，告别 403 和 429 封锁

[获取住宅代理](https://dashboard.marsproxies.com/products/ultra-residential-proxies#buy-now)

## 结合代理与反封锁策略重试 Python 请求

当您大规模抓取网站或调用 API 时，可能会遇到简单重试无法解决的封锁或 CAPTCHA。这时就需要用到[住宅代理](https://marsproxies.cn/proxies/residential-proxies/)。使用住宅代理意味着将您的 HTTP 请求通过另一台服务器（或一组服务器）转发，使目标网站看到的是[不同的 IP 地址](https://marsproxies.cn/blog/generate-random-ip-address/)。

### 为什么代理对重试请求很重要

设想这样一个场景：您在短时间内发送了多次请求，随后开始收到 403 Forbidden 或 429 Too Many Requests 响应，这可能意味着您的 IP 已被服务器标记或临时封禁。

如果仅用同一个 IP 重试，很可能会持续被封锁（甚至使情况恶化）。而在重试时切换到不同的代理 IP，下一次尝试可能会成功，因为服务器会将其视为新的请求来源。简而言之，代理服务器可以为您提供一次全新的身份。

代理在访问受地域限制的内容时也很有用。如果某个网站只对特定地区提供服务，就需要使用该允许地区的代理。在重试场景中，网络爬取领域常见的策略是：如果请求因 IP 被封而失败，就轮换到下一个代理再试一次。

由于每次请求不再来自同一个地址，这种方式能提高多次尝试的整体请求成功率。

### 在使用代理时调整重试逻辑

将代理整合进重试逻辑需要做一些调整。如果您使用的是 *HTTPAdapter* 方案，可以通过 proxies 参数在 Session 或单次请求上指定代理，例如：

```typescript
proxies = {
    "http" : "http://USERNAME:PASSWORD@proxy.server:port" ,
    "https" : "http://USERNAME:PASSWORD@proxy.server:port"
}
response = session. get (url, proxies=proxies, timeout= 10 )
```

您可以设置 Session 使用默认代理，但通常您会希望每次重试时更换代理。

在自定义重试循环中，您可以这样处理：

```python
proxy_pool = [ "proxy1.com:8000" , "proxy2.com:8000" , . . . ]  # list of proxy addresses
for attempt in range (max_retries) :
    proxy = proxy_pool[attempt % len (proxy_pool) ]
    try :
        resp = requests.get(url, proxies= { "http" : proxy, "https" : proxy} , timeout= 10 )
        if resp.status_code == 200 :
            return resp
        elif resp.status_code in [ 403 , 429 ] :
            print ( "Got {}, switching proxy and retrying..." . format (resp.status_code) )
            # continue to next attempt with a new proxy
        else :
            break  # for other status codes, break out (non-retryable)
    except requests.exceptions.RequestException as e:
        # If a proxy itself fails (e.g., connection error), try next proxy
        print ( "Proxy {} failed, trying next proxy..." . format (proxy) )
```

在这段伪代码中，如果收到 403 或 429，我们就认为是被封锁所致，并在下一轮迭代中切换到下一个代理。如果某个代理直接连接失败，则捕获该异常并同样切换到下一个代理。

### 实现基本的代理轮换

如上所示，一种基本的代理轮换策略是：维护一份代理服务器列表，并在每次重试时选用不同的代理，可以随机打乱顺序，也可以按顺序循环使用。

请务必提前测试您的代理。如果轮换列表中包含完全无法使用的代理，只会增加全部失败的重试次数。一些开发者会为每个代理单独创建一个 Session 对象，或维护一个预先配置好代理的 Session 池，以避免每次尝试都要重新构建 Session。

### 代理管理相关的库与工具

管理代理服务器可能会变得相当复杂，尤其是当您需要用到几十个甚至上百个 IP 时。以下是一些可以提供帮助的工具和服务：

- 代理轮换服务

像 [MarsProxies](https://marsproxies.cn/proxies/residential-proxies/) 这样的公司提供代理网络，甚至还提供可自动为您轮换代理的 API。

- 开源库

有一些 Python 库，例如 requests-ip-rotator 或 scrapeops-python-proxy，可以接入 requests 来实现代理轮换。

- Scrapy 等框架

如果您的项目规模较大，像 Scrapy 这样的网络爬取框架内置了对代理中间件和轮换功能的支持。

- 自行实现

对于较简单的需求，您可能并不需要专门的库。一份代理列表加上 requests 的 proxies 参数，往往就足以应对大部分情况。

## 重试请求的最佳实践

我们已经介绍了实现重试的多种方式。在结束操作部分之前，来总结一些为 [Python](https://marsproxies.com/blog/python-data-normalization-complete-guide/) 脚本添加重试能力时的最佳实践：

- 限制总重试次数

限制重试次数非常重要。如果服务处于宕机状态，不要让程序陷入无休止的重试循环：这样只会浪费资源，甚至可能永远无法恢复。

- 使用指数退避（避免零延迟或固定延迟）

务必引入退避系数，逐步增加各次尝试之间的等待时间，以防止对服务器造成冲击。

- 为每次请求设置超时

每个请求都应设置超时（如适用，应同时包含连接超时和读取超时）。

- 记录重试过程与结果

在调试或监控时，为重试过程添加日志记录会很有帮助。

- 避免重试非幂等操作（或谨慎处理）

如前文所述，对不适合重复执行的请求进行重试时要格外谨慎。如果必须重试可能导致重复操作的 POST 或 PUT 请求，应考虑在服务器端做好安全处理重复请求的设计。

- 遵循速率限制与退避信号

重试逻辑不应忽视服务器给出的信号。如果收到 429 响应或表示需要放慢速度的请求头，应将其纳入重试逻辑中。

## 结论

在本文中，我们探讨了如何使用 Python 的 requests 库有效地实现 HTTP 请求重试。我们首先了解了失败发生的原因，涵盖从短暂的网络问题到服务器端错误等各种情况，并强调了智能重试的重要性：只在确有必要时重试，并避免无限循环或过于激进的重试策略。

如果 Python 不适合您的项目，可以参考我们的[Golang vs Python](https://marsproxies.cn/blog/golang-vs-python/) 对比文章，了解不同语言在数据抓取与 HTTP 任务中的表现差异。此外，也可以查看我们关于[HTTPX vs Requests vs AIOHTTP](https://marsproxies.cn/blog/httpx-vs-requests-vs-aiohttp/)的文章。

想获取更多技巧与数据洞察，或想分享您在特定网站上的经验？欢迎加入我们的[Discord 社区](https://discord.com/invite/YJWrbVq8at/)！

urllib3 中的 Retry 类可以重试 POST 请求吗？

可以，但需要进行相应配置。默认情况下，Python requests 的重试机制会排除 POST 请求，但您可以在重试策略中将其启用。

如果响应状态码为 200 但内容包含错误，该如何重试 Python 请求？

使用自定义重试逻辑来检查响应内容。200 状态码本身不会自动触发对失败请求的重试。

backoff\_factor 与使用固定延迟进行重试有什么区别？

退避系数会逐步增加各次重试之间的等待时间，而固定延迟始终保持不变，可能会给服务器带来过大压力。

可以根据超时或连接错误等特定异常来决定是否重试请求吗？

可以，您可以捕获超时或连接错误等特定异常，从而有选择地对失败的请求进行重试。

在 requests 库中结合代理使用时，应如何处理重试？

每次重试时轮换 IP 以避免被封锁，并始终确保重试策略与最新的代理配置保持同步。

[了解更多](https://dashboard.marsproxies.com/register/)

\-

作者

[Dalius Pamedytis 软件工程师](https://marsproxies.cn/blog/authors/dalius-pamedytis/)

目录

1. [请求失败的常见原因](https://marsproxies.cn/blog/python-requests-retry/#b-%E8%AF%B7%E6%B1%82%E5%A4%B1%E8%B4%A5%E7%9A%84%E5%B8%B8%E8%A7%81%E5%8E%9F%E5%9B%A0)
2. [使用 HTTPAdapter 重试 Python 请求](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BD%BF%E7%94%A8-httpadapter-%E9%87%8D%E8%AF%95-python-%E8%AF%B7%E6%B1%82)
3. [How built-in retries work in requests](https://marsproxies.cn/blog/python-requests-retry/#b-how-built-in-retries-work-in-requests)
4. [示例：使用 Retry 配置 HTTPAdapter](https://marsproxies.cn/blog/python-requests-retry/#b-%E7%A4%BA%E4%BE%8B%E4%BD%BF%E7%94%A8-retry-%E9%85%8D%E7%BD%AE-httpadapter)
5. [需要调整的关键参数](https://marsproxies.cn/blog/python-requests-retry/#b-%E9%9C%80%E8%A6%81%E8%B0%83%E6%95%B4%E7%9A%84%E5%85%B3%E9%94%AE%E5%8F%82%E6%95%B0)
6. [自定义重试逻辑与装饰器](https://marsproxies.cn/blog/python-requests-retry/#b-%E8%87%AA%E5%AE%9A%E4%B9%89%E9%87%8D%E8%AF%95%E9%80%BB%E8%BE%91%E4%B8%8E%E8%A3%85%E9%A5%B0%E5%99%A8)
7. [基于 Try/Except 的重试循环](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%9F%BA%E4%BA%8E-tryexcept-%E7%9A%84%E9%87%8D%E8%AF%95%E5%BE%AA%E7%8E%AF)
8. [带抖动的指数退避](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%B8%A6%E6%8A%96%E5%8A%A8%E7%9A%84%E6%8C%87%E6%95%B0%E9%80%80%E9%81%BF)
9. [使用 tenacity 库实现重试](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BD%BF%E7%94%A8-tenacity-%E5%BA%93%E5%AE%9E%E7%8E%B0%E9%87%8D%E8%AF%95)
10. [何时应优先选用自定义逻辑而非 HTTPAdapter](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BD%95%E6%97%B6%E5%BA%94%E4%BC%98%E5%85%88%E9%80%89%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%BB%E8%BE%91%E8%80%8C%E9%9D%9E-httpadapter)
11. [处理 429 和 503 等 HTTP 状态码](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%A4%84%E7%90%86-429-%E5%92%8C-503-%E7%AD%89-http-%E7%8A%B6%E6%80%81%E7%A0%81)
12. [结合代理与反封锁策略重试 Python 请求](https://marsproxies.cn/blog/python-requests-retry/#b-%E7%BB%93%E5%90%88%E4%BB%A3%E7%90%86%E4%B8%8E%E5%8F%8D%E5%B0%81%E9%94%81%E7%AD%96%E7%95%A5%E9%87%8D%E8%AF%95-python-%E8%AF%B7%E6%B1%82)
13. [为什么代理对重试请求很重要](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BB%A3%E7%90%86%E5%AF%B9%E9%87%8D%E8%AF%95%E8%AF%B7%E6%B1%82%E5%BE%88%E9%87%8D%E8%A6%81)
14. [在使用代理时调整重试逻辑](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%9C%A8%E4%BD%BF%E7%94%A8%E4%BB%A3%E7%90%86%E6%97%B6%E8%B0%83%E6%95%B4%E9%87%8D%E8%AF%95%E9%80%BB%E8%BE%91)
15. [实现基本的代理轮换](https://marsproxies.cn/blog/python-requests-retry/#b-%E5%AE%9E%E7%8E%B0%E5%9F%BA%E6%9C%AC%E7%9A%84%E4%BB%A3%E7%90%86%E8%BD%AE%E6%8D%A2)
16. [代理管理相关的库与工具](https://marsproxies.cn/blog/python-requests-retry/#b-%E4%BB%A3%E7%90%86%E7%AE%A1%E7%90%86%E7%9B%B8%E5%85%B3%E7%9A%84%E5%BA%93%E4%B8%8E%E5%B7%A5%E5%85%B7)
17. [重试请求的最佳实践](https://marsproxies.cn/blog/python-requests-retry/#b-%E9%87%8D%E8%AF%95%E8%AF%B7%E6%B1%82%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5)
18. [结论](https://marsproxies.cn/blog/python-requests-retry/#b-%E7%BB%93%E8%AE%BA)

分类

- [产品动态](https://marsproxies.cn/blog/category/product-news/)

  [5](https://marsproxies.cn/blog/category/product-news/)
- [产品对比](https://marsproxies.cn/blog/category/comparisons/)

  [11](https://marsproxies.cn/blog/category/comparisons/)
- [反检测解决方案](https://marsproxies.cn/blog/category/antidetect-solution/)

  [3](https://marsproxies.cn/blog/category/antidetect-solution/)
- [操作指南](https://marsproxies.cn/blog/category/how-to/)

  [127](https://marsproxies.cn/blog/category/how-to/)
- [球鞋抢购机器人](https://marsproxies.cn/blog/category/sneaker-bots/)

  [2](https://marsproxies.cn/blog/category/sneaker-bots/)
- [资讯](https://marsproxies.cn/blog/category/insights/)

  [91](https://marsproxies.cn/blog/category/insights/)

## 相关文章

[操作指南](https://marsproxies.cn/blog/category/how-to/)

### [2026年如何用 Python 抓取 Yelp 数据](https://marsproxies.cn/blog/scrape-yelp-data/)

了解如何使用 Python 和 BeautifulSoup 抓取 Yelp 数据，本文提供防屏蔽与解析策略的详细步骤。

[Dalius Pamedytis 软件工程师](https://marsproxies.cn/blog/authors/dalius-pamedytis/)

2026年11月9日

[操作指南](https://marsproxies.cn/blog/category/how-to/)

### [YouTube 400 错误：含义及修复方法](https://marsproxies.cn/blog/youtube-error-400/)

YouTube 400 错误可能出现在 Android、iPhone、桌面端和电视端，了解其成因以及如何修复“服务器出现问题 \[400]”提示。

[Lukas Tilkevicius 增长与合作经理](https://marsproxies.cn/blog/authors/lukas-tilkevicius/)

2026年11月2日

[操作指南](https://marsproxies.cn/blog/category/how-to/)

### [Twitter 数据抓取 API：实用工具与使用方法](https://marsproxies.cn/blog/twitter-scraper-api/)

了解 Twitter 数据抓取 API 的工作原理，比较各类工具，并通过实用示例、技巧和实践经验，掌握如何抓取 Twitter 数据。

[Dalius Pamedytis 软件工程师](https://marsproxies.cn/blog/authors/dalius-pamedytis/)

2026年10月29日
