Python如何优雅地使用重试:tenacity

news/2024/11/25 19:20:07/

1 缘起

项目中使用了第三方服务,和上一篇文章一样:SpringBoot中如何优雅地使用重试https://blog.csdn.net/Xin_101/article/details/134617868
在调用第三方服务时,出现第三方服务连接不到的情况,为了保证服务的相对稳定,
当调用第三方服务出现异常时,进行重试,
本次的项目是Python语言开发的,因此,选择了灵活、功能强大的Tenacity框架。

2 Tenacity

https://tenacity.readthedocs.io/en/latest/
在这里插入图片描述

2.1 简介

Tenacity是Python的重试框架,用于简化重试逻辑的编写,
直接在Tenacity中提供的重试方法中配置相关参数即可实现重试功能,
参数化重试机制,如重试次数、时间间隔、重试的异常情况等,
提高开发效率。

2.2 retry方法

通过retry方法实现在指定异常情况下进行重试。
配置重试参数,在需要重试的方法上添加retry注解即可实现重试。
retry源码如下:
tenacity.retry
在这里插入图片描述

retry参数源码如下:
在这里插入图片描述

常用参数解析:

序号参数:描述
1max_retries最大重试次数
2retry_exception触发重试的异常类型
3reraise重新抛出异常开关:true:重新抛出异常;false:不重新抛出异常
4multiplier重试时间倍率,时间间隔:multiplier * 2^(n-1),n为执行次数
5min_seconds最小重试时间间隔
6max_seconds最大重试时间间隔

其中,

  • max_retries是执行的总次数,重试次数即为执行的总次数-1,如max_retries=5,重试4次,总共执行5次。
  • retry_exception用于配置重试的异常条件,即在何种异常出现时进行重试。
  • reraise是重试后是否抛出异常的标识,配置为true时,当达到重试最大次数时,重新抛出异常,给下游捕获,当配置为false时,不抛出异常。
  • min_seconds:最小时间间隔,当重试次数计算的时间间隔小于min_seconds时,使用min_seconds的值作为时间间隔,否则使用计算时间间隔。
  • max_seconds:最大时间间隔,当重试次数计算的时间间隔大于max_seconds时,使用max_seconds作为时间间隔,避免延迟时间爆炸,限定重试间隔上限/上边界。
  • multiplier用于配置重试时间间隔比率,时间间隔:multiplier * 2^(n-1),n为执行次数,这个可以参见源码,如下图所示,时间间隔为result=self.multiplier * exp,而exp=self.exp_base ** (retry_state.attempt_number - 1),因此时间间隔为:multiplier * 2^(n-1),最终的重试时间间隔是在计算结果result、最小时间间隔和最大时间间隔中取出的。
    位置:tenacity.wait.wait_exponential
    在这里插入图片描述

2.3 配置retry参数

这里我们对retry方法进行一层包装,有些多余,
先这样写吧,如下:
在这里插入图片描述

2.4 指定方法上使用retry

完成retry方法参数配置后,在需要重试的方法中使用retry框架,
首先初始化retry的方法,
然后在执行的方法上添加注解。
在这里插入图片描述
执行结果如下图所示,
按照上面的retry配置,可知min_seconds=4s,max_seconds=10s,max_retries=5,multiplier=1
即重试4次,

  • 时间间隔:第二次~第一次:time_interval=1*2^(2-1)=1s,time_interval<min_seconds,因此使用4s;
  • 时间间隔:第三次~第二次:time_interval=1*2^(3-1)=4s,time_interval=min_seconds,因此使用4s;
  • 时间间隔:第四次~第三次:time_interval=1*2^(4-1)=8s,min_seconds<time_interval<max_seconds,因此使用8s;

在这里插入图片描述

2.5 完整样例

"""
重试测试@author xindaqi
@since 2023-12-02 16:34
"""
from typing import Callable, Any
from datetime import datetime
import loggingfrom tenacity import (before_sleep_log,retry,retry_if_exception_type,stop_after_attempt,wait_exponential,
)logger = logging.getLogger(__name__)def retry_decorator(max_retries: int, retry_exception: "RetryBaseT" = retry_if_exception_type(), reraise=True, multiplier=1, min_seconds=4, max_seconds=10) -> Callable[[Any], Any]:"""重试装饰器:param max_retries: 最大重试次数:param retry_exception: 触发重试的异常类型:param reraise: 重新抛出异常开关:true:重新抛出异常;false:不重新抛出异常:param multiplier: 重试时间倍率,时间间隔:multiplier * 2^(n-1),n为执行次数:param min_seconds: 最小重试时间间隔:param max_seconds: 最大重试时间间隔:return: 重试对象"""return retry(reraise=reraise,stop=stop_after_attempt(max_retries),wait=wait_exponential(multiplier=multiplier, min=min_seconds, max=max_seconds),retry=retry_exception,before_sleep=before_sleep_log(logger, logging.WARNING),)def function_with_retry(max_retries, retry_exception):retry_decorator_init = retry_decorator(max_retries, retry_exception)@retry_decorator_initdef run():now = datetime.now()current_time = now.strftime("%Y-%m-%d %H:%M:%S")print(">>>>>>>>Current time:{}".format(current_time))a = 1/0return run()if __name__ == "__main__":exception = (retry_if_exception_type(ZeroDivisionError))function_with_retry(5, exception)

3 小结

(1)Tenacity重试框架,提供重试参数配置,简单易用,提高开发效率;
(2)重试参数有max_retries(最大执行次数)、reraise(重新抛出异常标识,如果达到重试次数上限后,是否抛出原生异常给上游调用方),min_seconds最小的时间间隔,即重试的时间间隔最小只能为min_seconds,max_seconds是最大时间间隔,即最大的延迟时间为max_seconds,为重试时间间隔做了限制,保证间隔的合理;
(3)重试时间间隔计算公式为:time_interval=multiplier*2^(n-1),n为重试次数,最终的延迟时间间隔从time_interval、min_seconds和max_seconds中取,计算公式:max(max(0, min_seconds), min(time_interval, max_seconds));
(4)Tenacity可以配置多种异常类型,当出现这些异常时进行重试,细粒度控制重试。


http://www.ppmy.cn/news/1255346.html

相关文章

SpringMVC常用注解和用法总结

目标&#xff1a; 1. 熟悉使用SpringMVC中的常用注解 目录 前言 1. Controller 2. RestController 3. RequestMapping 4. RequestParam 5. PathVariable 6. SessionAttributes 7. CookieValue 前言 SpringMVC是一款用于构建基于Java的Web应用程序的框架&#xff0c;它通…

WPF实现文字纵向排布的TabItem

文章目录 基本用法文字竖排显示 WPF布局 基本用法 WPF中的TabControl是一个容器控件&#xff0c;用于在单个窗体或页面中承载多个选项卡。每个选项卡可以包含不同的控件&#xff0c;用于显示不同的内容&#xff0c;其最简单的调用方法如下&#xff0c;只需在TabControl中无脑…

初识Linux:保姆级教学,让你一秒记住Linux中的常用指令!

文章目录 前言一、LInux的背景及发展史二、Linux下的基本指令1、ls指令2、pwd指令3、cd指令4、touch指令5、mkdir指令&#xff08;重要&#xff09;6、tree指令7、rmdir指令和rm指令&#xff08;重要&#xff09;8、man指令&#xff08;重要&#xff09;9、cp指令&#xff08;重…

Django rest froamwork-ModelSerializer

文章目录 1 检查ModelSerializer2 指定要包含的字段3 指定嵌套序列化4 显式指定字段5 指定只读字段6 其他关键字参数7 关系字段8 自定义字段映射.serializer_field_mapping.serializer_related_fieldserializer_url_field.serializer_choice_field 通常&#xff0c;您会想要与D…

构建第一个ArkTS应用(纯HarmonyOS应用)

1. 安装开发工具 在华为开发者官方上下载HarmonyOS应用专用的开发工具&#xff0c;链接地址&#xff1a;HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 要想使用开发工具让项目跑起来&#xff0c;需要10G的磁盘空间。开发工具需要的磁盘空间为2.36G&#xff1b;SDK需…

第7章-使用统计方法进行变量有效性测试-7.5-逻辑回归

目录 购房的启发 初建模型 多元逻辑回归模型 模型参数估计 极大似然估计

9. 双向队列

在队列中&#xff0c;我们仅能删除头部元素或在尾部添加元素。如下图所示&#xff0c;双向队列(double-ended queue)提供了更高的灵活性&#xff0c;允许在头部和尾部执行元素的添加或删除操作。 9.1 双向队列常用操作 双向队列的常用操作如下表所示&#xff0c;具体的方法名称…

JavaSE学习路线及经验所谈

前言 一.学习框架二.学习经验 相信很多小白刚开始学习Java时&#xff0c;都是靠自己在网上搜集资料&#xff0c;并没有明确规划&#xff0c;不知道要学习什么内容&#xff0c;也不知道学习的重点是什么&#xff0c;那么这篇文章会给你一个大致的指引&#xff0c;当然也可以作为…