重试retry 重试控制机制

retrying 是一个 Python 包,用于提供一个装饰器(以及一个重试控制机制),允许你将其应用于任何函数或方法上,使得在遇到特定的异常或者返回条件不满足时自动重试。使用 retrying 包中的 retry 函数可以帮助简化代码中处理瞬时错误或不稳定操作(如网络请求)的逻辑。

当你使用 @retry 装饰器装饰一个函数时,可以指定多个参数来控制重试行为,包括:

  • stop_max_attempt_number: 重试的最大次数。
  • stop_max_delay: 最大的重试延迟时间(毫秒),超过这个时间后不再重试。
  • wait_fixed: 两次重试之间的固定等待时间(毫秒)。
  • wait_random_minwait_random_max: 两次重试之间的随机等待时间的最小值和最大值(毫秒)。
  • retry_on_exception: 一个函数,当它返回 True 时,会在抛出的异常上重试。
  • retry_on_result: 一个函数,当目标函数返回值使得该函数返回 True 时进行重试。

例如,假设你有一个网络请求的函数,由于网络波动,你希望在遇到连接错误时自动重试,但最多重试3次,每次重试之间等待2秒:

from retrying import retry
import requests

@retry(stop_max_attempt_number=3, wait_fixed=2000)
def fetch_data(url):
    response = requests.get(url)
    response.raise_for_status()  # 如果响应码不是 200,会抛出异常
    return response.json()

# 使用这个函数,它会在失败时尝试最多3次,每次尝试之间等待2秒
data = fetch_data("https://example.com/api/data")

在这个例子中,如果 requests.get(url) 因为网络问题抛出异常(比如 requests.exceptions.ConnectionError),fetch_data 函数会自动重试,直到尝试了3次或者成功获取数据为止。

其它

import requests
from retry import retry
from requests.exceptions import RequestException

# 重试最多 3 次,捕获所有与请求相关的异常
@retry(RequestException, tries=3, delay=1, backoff=2, max_delay=3)
def fetch_page(url):
    print(f"正在尝试获取页面:{url}")
    response = requests.get(url)
    response.raise_for_status()  # 如果响应码不是 200,会抛出 HTTPError
    return response.text

try:
    url = "https://example1.com"
    page_content = fetch_page(url)
    print(page_content)
    print("成功获取页面内容")
except RequestException as e:
    print(f"请求失败:{e}")

参数解释:

  1. tries:
    • 控制最大重试次数。tries=3 表示最多重试 3 次,包含第一次的尝试。因此,最多会执行 4 次(1 次初始尝试 + 3 次重试)。
  2. delay:
    • 控制首次重试的延迟时间(单位:秒)。delay=1 表示第一次重试时会等待 1 秒钟。
    • 如果你设置了 backoff,第一次重试的时间间隔会根据 backoff 参数成倍增加。
  3. backoff:
    • 控制每次重试的时间间隔增长倍数。backoff=2 表示每次重试时,重试的时间间隔将是上次间隔的 2 倍(指数增长)。
    • 例如,如果第一次重试延迟 1 秒,第二次会延迟 2 秒,第三次会延迟 4 秒(依此类推)。
  4. max_delay:
    • 控制重试间隔的最大值。max_delay=3 表示每次重试的间隔时间不能超过 3 秒。
    • 即使根据 backoff 的规则,间隔时间大于 3 秒,系统也会限制为最多 3 秒。

示例:

假设 tries=3, delay=1, backoff=2, max_delay=3,重试行为如下:

  1. 第一次尝试:delay=1 秒(无延迟,直接尝试)。
  2. 如果第一次失败,第二次尝试会延迟:delay=1 * backoff = 2 秒。
  3. 如果第二次失败,第三次尝试会延迟:delay=2 * backoff = 4 秒,但由于 max_delay=3,会将延迟限制为 3 秒。

示例代码执行流程:

import requests
from retry import retry
from requests.exceptions import RequestException

# 重试最多 3 次,每次重试延迟 1 秒,之后按 2 倍增长,最大间隔为 3 秒
@retry(RequestException, tries=3, delay=1, backoff=2, max_delay=3)
def fetch_page(url):
    print(f"正在尝试获取页面:{url}")
    response = requests.get(url)
    response.raise_for_status()  # 如果响应码不是 200,会抛出 HTTPError
    return response.text

try:
    url = "https://example1.com"
    page_content = fetch_page(url)
    print(page_content)
    print("成功获取页面内容")
except RequestException as e:
    print(f"请求失败:{e}")

执行过程:

  1. 第一次请求,如果失败,等待 1 秒钟后重试。
  2. 第二次请求,如果失败,等待 2 秒钟后重试。
  3. 第三次请求,如果失败,等待 3 秒钟后重试(注意:此时会达到最大延迟限制 max_delay=3,即使根据 backoff 应该等待更长时间,也会将其限制为 3 秒)。
  4. 如果所有尝试都失败,会触发 RequestException 并进入 except 语句。
posted @ 2024-03-22 22:54  __username  阅读(184)  评论(0编辑  收藏  举报

本文作者:DIVMonster

本文链接:https://www.cnblogs.com/guangzan/p/12886111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。