使用 Python 装饰器重试代码块
我们可以用装饰器修改一个函数或类来扩展函数的行为,而不用永久地改变它。 本文讨论如何使用重试装饰器修改现有函数而不更改所述函数。
在这种情况下,修改会在给定情况下多次重试函数,其返回值可能与我们想要的不同。
@retry 装饰器的重要性
我们可以使用装饰器来扩展特定函数的行为,我们可以轻松地创建装饰器来修改该函数,即使我们无法访问它或不想更改它。
我们可能经常需要该函数的特定方式,这就是 Python 装饰器的用武之地。所以让我们创建一个简单的函数来展示装饰器的工作原理。
简单的函数 quotient()
接受两个参数并将第一个参数除以第二个参数。
def quotient(a, b):
return a / b
print(quotient(3, 7))
输出:
0.42857142857142855
但是,如果我们希望除法结果始终是较大的数被除(因此结果将是 2.3333333333333335),我们可以更改代码或使用装饰器。
使用装饰器,我们可以在不更改其代码块的情况下扩展函数的行为。
def improv(func):
def inner(a, b):
if a < b:
a, b = b, a
return func(a, b)
return inner
@improv
def quotient(a, b):
return a / b
print(quotient(3, 7))
输出:
2.3333333333333335
improv()
函数是一个装饰函数,它将 quotient()
函数作为其参数,并包含一个内部函数,该函数采用 quotient()
函数的参数并引入您需要添加的附加功能。
现在,使用装饰器,我们可以在特定函数上添加重试功能,尤其是对于我们无权访问的函数。
重试装饰器在可能存在不可预测的行为或错误的情况下很有用,并且您希望在它们发生时再次重试相同的操作。
一个典型的例子是在 for 循环中处理失败的请求。 在这种情况下,我们可以使用 @retry
装饰器来管理重试该特定请求指定次数。
在 Python 中使用 @retry 重试代码块
对于重试装饰器,有不同的库提供此功能,其中一个库是 retrying 库。
使用它,您可以指定从 Exceptions 到预期返回结果的等待和停止条件。 要安装 retrying 库,我们可以使用 pip
命令,如下所示:
$ pip install retrying
现在,让我们创建一个函数,它随机创建 0 到 10 之间的数字,但当我们遇到数字大于 1 的情况时会引发 ValueError。
import random
def generateRandomly():
if random.randint(0, 10) > 1:
raise ValueError("Number generated is greater than one")
else:
return "Finally Generated."
print(generateRandomly())
如果此时生成的数字大于 1,代码输出将如下所示。
Traceback (most recent call last):
File "c:\Users\jiyik\Documents\Python\SFTP\test.py", line 11, in <module>
print(generateRandomly())
File "c:\Users\jiyik\Documents\Python\SFTP\test.py", line 6, in generateRandomly
raise ValueError("Number generated is greater than one")
ValueError: Number generated is greater than one
我们不能在代码中抛出 ValueError 的情况,因此我们可以引入重试装饰器来重试 generateRandomly() 函数,直到它不引发 ValueError。
import random
from retrying import retry
@retry
def generateRandomly():
if random.randint(0, 10) > 1:
raise ValueError("Number generated is greater than one")
else:
return "Finally Generated."
print(generateRandomly())
输出:
Finally Generated.
现在,重试装饰器重试随机操作,直到它没有 ValueError,我们只有字符串 Finally Generated..
通过在 if 块中引入 print()
语句,我们可以看到代码重试 generateRandomly()
的次数。
import random
from retrying import retry
@retry
def generateRandomly():
if random.randint(0, 10) > 1:
print("1")
raise ValueError("Number generated is greater than one")
else:
return "Finally Generated."
print(generateRandomly())
输出:
1
1
1
1
1
1
1
Finally Generated.
此处为 8,但运行代码时可能会有所不同。 但是,我们不能出现代码一直重试很长时间的情况。 所以,我们有像 stop_max_attempt_number 和 stop_max_delay 这样的参数。
import random
from retrying import retry
@retry(stop_max_attempt_number=5)
def generateRandomly():
if random.randint(0, 10) > 1:
print("1")
raise ValueError("Number generated is greater than one")
else:
return "Finally Generated."
print(generateRandomly())
输出:
1
1
1
Finally Generated.
该函数只重试了 5 次,但要么在第 5 次之前成功,返回值 Finally Generated.,要么不成功并抛出 ValueError。
1
1
1
1
1
File "C:\Python310\lib\site-packages\retrying.py", line 247, in get
six.reraise(self.value[0], self.value[1], self.value[2])
File "C:\Python310\lib\site-packages\six.py", line 719, in reraise
raise value
File "C:\Python310\lib\site-packages\retrying.py", line 200, in call
attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
File "c:\Users\jiyik\Documents\Python\SFTP\test.py", line 9, in generateRandomly
raise ValueError("Number generated is greater than one")
ValueError: Number generated is greater than one
使用 tenacity 重试 Python 中的代码块
重试库可能有点古怪,不再维护,但坚韧库提供了所有功能,并提供了更多工具。
要安装 tenacity,请使用以下 pip 命令:
pip install tenacity
我们可以在 3 停止尝试来尝试相同的代码。
import random
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
def generateRandomly():
if random.randint(0, 10) > 1:
print("1")
raise ValueError("Number generated is greater than one")
else:
return "Finally Generated."
print(generateRandomly())
如果在三次尝试时间范围内生成的随机数小于 1,则代码的输出。
1
Finally Generated.
The above exception was the direct cause of the following exception:
1
1
1
Traceback (most recent call last):
File "C:\Python310\lib\site-packages\tenacity\__init__.py", line 407, in __call__
result = fn(*args, **kwargs)
File "c:\Users\jiyik\Documents\Python\SFTP\test.py", line 9, in generateRandomly
raise ValueError("Number generated is greater than one")
ValueError: Number generated is greater than one
上述异常是以下异常的直接原因:
Traceback (most recent call last):
File "c:\Users\akinl\Documents\Python\SFTP\test.py", line 14, in <module>
print(generateRandomly())
File "C:\Python310\lib\site-packages\tenacity\__init__.py", line 324, in wrapped_f
return self(f, *args, **kw)
File "C:\Python310\lib\site-packages\tenacity\__init__.py", line 404, in __call__
do = self.iter(retry_state=retry_state)
File "C:\Python310\lib\site-packages\tenacity\__init__.py", line 361, in iter
raise retry_exc from fut.exception()
tenacity.RetryError: RetryError[<Future at 0x29a75442c20 state=finished raised ValueError>]
相关文章
Python 装饰器顺序
发布时间:2023/06/17 浏览次数:192 分类:Python
-
在这篇 Python 文章中,我们将了解什么是装饰器、它们的使用方式以及我们如何利用它们来构建代码。 我们将看到装饰器是如何成为一种强大的工具,可以用来为我们的应用程序添加功能,并且
Python 中的 super参数
发布时间:2023/06/17 浏览次数:158 分类:Python
-
本文的主题是正确使用 Python 超级参数。 我们还将了解超和继承的概念、使用超参数的适当代码示例以及基类的概念。Python 中的 super 参数 在 Python 中,super 调用另一个类的方法。
将 Kwargs 传递给 Python 中的另一个函数
发布时间:2023/06/17 浏览次数:128 分类:Python
-
Python 将 kwargs 参数表示为关键字参数,可以在参数名称前使用两个星号传递参数数量。 通过这篇文章,我们寻找 Python 如何将 kwargs 传递给另一个函数。
在 Python 中打印度数符号
发布时间:2023/06/17 浏览次数:191 分类:Python
-
本篇文章将介绍如何用 Python 编写度数符号。度数符号是表示特定区域温度的符号。 例如,假设卡纳塔克邦的气温为 34 摄氏度; 它表明,在印度卡纳塔克邦,温度为 34 度
Python 中的 @ 符号
发布时间:2023/06/17 浏览次数:138 分类:Python
-
Python 中 @ 符号最常见的用例是装饰器。 装饰器允许您更改函数或类的行为。@ 符号也可以用作数学运算符,因为它可以在 Python 中乘以矩阵。 本教程将教您使用 Python 的 @ 符号。
Python 堆排序
发布时间:2023/06/17 浏览次数:184 分类:Python
-
本篇文章将介绍堆排序算法在 Python 中的实现。Python中的堆排序算法 堆排序是一种强大的算法,用于在 Python 中对数组和列表进行排序。 它很受欢迎,因为它非常快,并且不像合并排序和快速排
Python 拓扑排序
发布时间:2023/06/17 浏览次数:102 分类:Python
-
本篇文章将介绍拓扑排序算法在 Python 中的实现。Python 中的拓扑排序算法 拓扑排序算法对有向无环图 (DAG) 进行排序。
在 Python 中对日期和时间进行排序
发布时间:2023/06/17 浏览次数:82 分类:Python
-
在本文中,我们讨论了如何在 Python 中使用 sorted() 方法对日期和时间进行排序。 为了理解这个概念,我们举了一些例子以及 Python 中的 datetime 模块。
Python 双样本 T 检验
发布时间:2023/06/17 浏览次数:94 分类:Python
-
Python 为我们提供的一个功能是我们可以执行双样本 t 检验。 通过本文,我们将讨论什么是双样本 t 检验以及如何使用 Python 执行它。