python-重试库-retrying

本文介绍了Python中的retry、retrying和tenacity三个重试库,详细讲解了retrying库的安装、用法,包括使用装饰器、自定义重试策略,并给出了实例代码。重试库在处理函数调用时的错误提供了便利,可以根据需求选择合适的库来实现重试机制。
摘要由CSDN通过智能技术生成

retry、retrying和tenacity是Python中常用的三个模块,用于处理函数调用时的重试机制。它们的主要区别如下:

  • retry模块:
    • 是一个简单的模块,提供了一个简单的重试机制。它通过在调用失败时自动重试一定次数来帮助您处理错误。
    • 可以通过设置参数来控制重试次数、重试间隔等。
    • 可以通过Retry类来定义自己的重试策略。
  • retrying模块:
    • 是一个基于contextlib的模块,提供了一个更高级的重试机制。它通过使用上下文管理器来处理函数调用,并在调用失败时自动重试。
    • 可以通过设置参数来控制重试次数、重试间隔等。
    • 可以通过Retry类来定义自己的重试策略。
    • 可以使用@retrying装饰器来包装需要重试的函数。
  • tenacity模块:
    • 是一个功能强大的模块,提供了一个更灵活的重试机制。它通过使用装饰器来处理函数调用,并在调用失败时自动重试。
    • 可以通过设置参数来控制重试次数、重试间隔等。
    • 可以通过Retrying类来定义自己的重试策略。
    • 可以使用@tenacity.retrying装饰器来包装需要重试的函数。

总的来说,这三个模块都可以用于处理函数调用时的重试机制,但它们的使用方式和功能略有不同。根据您的需求和偏好,可以选择适合您的模块来使用。

程序运行过程中,经常遇到失败的情况,这个时候我们一般会通过try块去进行重试,但是每次都写那么一堆try块,太麻烦。于是就有了retrying模块

安装

retrying模块的安装很简单直接用匹配安装即可。

pip install retrying

用法

retrying 模块是一个用于在Python中进行延迟重试的装饰器,它可以处理大多数常见的异常。下面是retrying模块的常见用法:

使用装饰器

使用@retrying装饰器可以重试某个函数,最多尝试次数由stop_after_attempt参数指定。如果成功执行函数,则停止重试。如果遇到异常,则重新尝试。

def __init__(self,
             stop: Any = None,
             wait: Any = None,
             stop_max_attempt_number: Any = None,
             stop_max_delay: Any = None,
             wait_fixed: Any = None,
             wait_random_min: Any = None,
             wait_random_max: Any = None,
             wait_incrementing_start: Any = None,
             wait_incrementing_increment: Any = None,
             wait_incrementing_max: Any = None,
             wait_exponential_multiplier: Any = None,
             wait_exponential_max: Any = None,
             retry_on_exception: Any = None,
             retry_on_result: Any = None,
             wrap_exception: bool = False,
             stop_func: Any = None,
             wait_func: Any = None,
             wait_jitter_max: Any = None,
             before_attempts: Any = None,
             after_attempts: Any = None) -> None

默认行为是永久重试而不等待。

  • stop_max_attempt_number:在停止之前尝试的最大次数,最后一次如果还是有异常则会抛出异常,停止运行,默认为5次

  • stop_max_delay:最大延迟时间,大概意思就是:如果调用的函数出现异常,那么就会重复调用这个函数,最大调用时间,默认为100毫秒

  • wait_fixed:两次调用方法期间停留时长, 如果出现异常则会一直重复调用,默认 1000毫秒

  • wait_random_min:在两次调用方法停留时长,停留最短时间,默认为0

  • wait_random_max:在两次调用方法停留时长,停留最长时间,默认为1000毫秒

  • wait_incrementing_startwait_incrementing_increment:每调用一次则会增加的时长,默认 100毫秒

  • wait_exponential_multiplierwait_exponential_max:以指数的形式产生两次retrying之间的停留时间,产生的值为2^previous_attempt_number * wait_exponential_multiplierprevious_attempt_number是前面已经retry的次数,如果产生的这个值超过了wait_exponential_max的大小,那么之后两个retrying之间的停留值都为wait_exponential_max

  • retry_on_exception: 指定一个函数,如果此函数返回指定异常,则会重试,如果不是指定的异常则会退出

    retry_on_exception参数的大体思想是:接收一个自定义函数is_MyError,在is_MyError函数里判断了是不是属于ValueError, IOError, ConnectionError三种异常;random_with_retry()函数如果抛出了异常,会去函数is_MyError()判断返回的是True还是False,如果是True则继续重试,如果是False则立即停止并抛出异常。

  • retry_on_result:指定一个函数,如果指定的函数返回True,则重试,否则抛出异常退出

    判断业务函数返回哪些结果时需要重试,思想和retry_on_exception参数类似。

  • wrap_exception:参数设置为True/False,如果指定的异常类型,包裹在RetryError中,会看到RetryError和程序抛的Exception error

  • stop_func: 每次抛出异常时都会执行的函数,如果和stop_max_delay、stop_max_attempt_number配合使用,则后两者会失效指定的。 stop_func会有两个参数:attempts, delay

  • wait_func:和stop_func用法差不多,不多描述

例如:

from retrying import retrying

@retrying(stop_after_attempt=3, wait_random_min=1, wait_random_max=2)
def my_function():
    # your function here
    pass

在这个例子中,如果my_function在3次尝试中仍然抛出异常,它将尝试最多4次,每次等待1到2秒之间随机的时间。如果my_function在3次尝试中仍然抛出异常,它将会在后续尝试中被重新调用。

自定义重试策略

除了使用默认的策略外,还可以自定义重试策略。自定义策略需要实现RetryStrategy接口,并实现should_retry()方法。在实现自定义策略时,可以设置最大尝试次数、等待时间等参数。

例如:

from retrying import RetryStrategy, RetryOnException, RetryOnTimeout, RetryOnMaxRetriesExceeded
from time import sleep

class CustomStrategy(RetryStrategy):
    def should_retry(self, attempt_number, exception):
        return attempt_number < 5 and isinstance(exception, (Exception,)) and not self.is_timeout(exception)

    def is_timeout(self, exception):
        return False  # 设置自定义的超时策略,此处不进行超时判断

my_strategy = CustomStrategy()
my_function = retrying(stop_after_attempt=5, strategy=my_strategy)

在这个例子中,自定义了重试策略,其中should_retry()方法返回True表示需要重试,is_timeout()方法返回False表示没有超时。当my_function在5次尝试中仍然抛出异常时,它将尝试最多6次,每次等待1到2秒之间随机的时间。如果my_function在5次尝试中仍然抛出异常,它将会在后续尝试中被重新调用。

下面是一个使用retrying实现自定义重试策略的例子:

from retrying import retry

@retry(wait_between=10)
def download_file(url):
    try:
        response = requests.get(url)
        return response.content
    except Exception as e:
        print(f"Error downloading file: {e}")
        return None

在这个例子中,我们定义了一个名为download_file的函数,它接受一个URL作为参数,并尝试从该URL下载文件。如果下载过程中发生错误,函数将返回None。如果下载成功,函数将返回文件的二进制内容。

我们使用@retry装饰器来定义一个自定义的重试策略。在这个例子中,我们使用了wait_between参数来指定每次重试之间的等待时间。这个参数的默认值为10秒。如果下载过程中发生错误,retrying将尝试重新下载文件,最多重试5次。如果下载成功,函数将返回文件的二进制内容。如果下载失败,函数将返回None。

需要注意的是,retrying库中的重试策略是固定的,无法根据具体情况进行调整。如果需要更灵活的重试策略,可以考虑使用其他库,例如Retrying、treq等。

retrying模块中的Retrying类提供了以下方法:

  • @retrying(stop_max_attempt_number=10, wait_fixed=100):装饰器形式的重试策略,可以设置最大重试次数和每次重试的等待时间。
  • Retrying(stop_max_attempt_number=10, wait_fixed=100):类形式的重试策略,可以设置最大重试次数和每次重试的等待时间。

下面是一个示例代码,演示如何使用retrying模块实现自定义的重试策略:

import time
from retrying import Retrying

# 定义一个可重试函数
def request_api(url, method='get', params=None):
    # 模拟网络请求的失败和成功操作
    print('request:', url, method)
    time.sleep(2)  # 模拟网络请求失败
    return 'success'

# 定义一个自定义的重试策略
def custom_retry_strategy(exception):
    # 判断是否是网络请求失败导致的异常
    if isinstance(exception, ConnectionError):
        return True
    return False

# 创建自定义的重试策略对象
retrying = Retrying(stop_max_attempt_number=3, wait_fixed=100)
custom_retry = retrying(custom_retry_strategy)

# 调用可重试函数并重试三次,最多只执行三次
try:
    response = custom_retry(request_api, url='https://example.com/api', method='post', params={'key': 'value'})
    print('response:', response)
except Exception as e:
    print('error:', e)

在上面的示例代码中,我们定义了一个可重试函数request_api,它模拟了一个网络请求的操作。然后,我们定义了一个自定义的重试策略custom_retry_strategy,用于判断是否是网络请求失败导致的异常。最后,我们创建了一个自定义的重试策略对象custom_retry,并使用它来调用可重试函数request_api,最多只执行三次。如果发生异常,将会进行三次重试,直到成功为止。

最大重试次数

from retrying import retry


@retry(stop_max_attempt_number=5)
def do_something_limited():
    print("do something several times")
    raise Exception("raise exception")


do_something_limited()

限制最长重试时间(从执行方法开始计算)

from retrying import retry

@retry(stop_max_delay=5000)
def do_something_in_time():
    print("do something in time")
    raise Exception("raise exception")


do_something_in_time()

设置固定重试时间

from retrying import retry


@retry(wait_fixed=2000)
def wait_fixed_time():
    print("wait")
    raise Exception("raise exception")


wait_fixed_time()

设置重试时间的随机范围

from retrying import retry


@retry(wait_random_min=1000, wait_random_max=2000)
def wait_random_time():
    print("wait")
    raise Exception("raise exception")


wait_random_time()

retry_on_exception参数

# 自己定义一个函数,判断异常类型,然后将函数作为参数传给装饰函数 retry ,如果异常类型符合,就会进行重试。
from retrying import retry


# 根据异常重试
def retry_if_io_error(exception):
    return isinstance(exception, IOError)


# 设置特定异常类型重试
@retry(retry_on_exception=retry_if_io_error)
def retry_special_error():
    print("retry io error")
    raise IOError("raise exception")


retry_special_error()

retry_on_result参数

# 定义了一个判断返回值的函数,然后将这个函数作为参数传给 retry 装饰函数。当结果返回是“111”时,就会一直重试执行 might_return_none 函数。
from retrying import retry

# 通过返回值判断是否重试
def retry_if_result_none(result):
    """Return True if we should retry (in this case when result is None), False otherwise"""
    # return result is None
    if result == "111":
        return True


@retry(retry_on_result=retry_if_result_none)
def might_return_none():
    print("Retry forever ignoring Exceptions with no wait if return value is None")
    return "111"


might_return_none()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

士别三日,当挖目相待

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值