我在Python
2.7写作并遇到以下情况。我想尝试三次调用函数。如果所有三次都出错,我会提出我得到的最后一个错误。如果任何一个呼叫成功,我将退出尝试并立即继续。
这就是我现在所拥有的:
output = None
error = None
for _e in range(3):
error = None
try:
print 'trial %d!' % (_e + 1)
output = trial_function()
except Exception as e:
error = e
if error is None:
break
if error is not None:
raise error
是否有更好的代码段可以实现相同的用例?
答案 0 :(得分:4)
使用装饰器
from functools import wraps
def retry(times):
def wrapper_fn(f):
@wraps(f)
def new_wrapper(*args,**kwargs):
for i in range(times):
try:
print 'try %s' % (i + 1)
return f(*args,**kwargs)
except Exception as e:
error = e
raise error
return new_wrapper
return wrapper_fn
@retry(3)
def foo():
return 1/0;
print foo()
答案 1 :(得分:3)
这是一种可能的方法:
def attempt(func, times=3):
for _ in range(times):
try:
return func()
except Exception as err:
pass
raise err
带有print
语句的演示:
>>> attempt(lambda: 1/0)
Attempt 1
Attempt 2
Attempt 3
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
attempt(lambda: 1/0)
File "<pyshell#17>", line 8, in attempt
raise err
ZeroDivisionError: integer division or modulo by zero
答案 2 :(得分:1)
忽略调试输出和古老的Python方言,这看起来不错。我唯一要改变的是将它放入一个函数中,然后你可以简单地返回trial_function()的结果。此外,error = None
变得不必要,包括相关的检查。如果循环终止,则必须设置错误,因此您可以抛出它。如果您不想要一个函数,可以考虑将else
与for循环结合使用,并在第一个结果后使用。
for i in range(3):
try:
result = foo()
break
except Exception as error:
pass
else:
raise error
use_somehow(result)
当然,使用装饰器进行功能的建议仍然存在。你也可以在本地应用它,装饰器语法毕竟只是语法糖:
# retry from powerfj's answer below
rfoo = retry(3)(foo)
result = rfoo()
答案 3 :(得分:1)
遇到了一种干净的重试方式。有一个名为 retry 的模块。
首先使用
安装模块pip install retry
然后在代码中导入模块。
from retry import retry
在方法上方使用@retry
装饰器,我们可以将参数传递给装饰器。一些参数是 tries
、 delay
、 Exception
。
示例
from retry import retry
@retry(AssertionError, tries=3, delay=2)
def retryfunc():
try:
ret = False
assert ret, "Failed"
except Exception as ex:
print(ex)
raise ex