Mai*_*Mai 2 python error-handling design-patterns
我在Python
2.7写的,遇到如下情况。我想尝试调用一个函数三次。如果所有 3 次都引发错误,我将引发我得到的最后一个错误。如果任何一个调用成功,我将停止尝试并立即继续。
这是我现在所拥有的:
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
Run Code Online (Sandbox Code Playgroud)
是否有更好的片段可以实现相同的用例?
这是一种可能的方法:
def attempt(func, times=3):
for _ in range(times):
try:
return func()
except Exception as err:
pass
raise err
Run Code Online (Sandbox Code Playgroud)
带有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
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 Python 3.x 并获得一个UnboundLocalError
,则可以进行如下调整:
def attempt(func, times=3):
to_raise = None
for _ in range(times):
try:
return func()
except Exception as err:
to_raise = err
raise to_raise
Run Code Online (Sandbox Code Playgroud)
这是因为err
在try
语句结束时清除了;根据文档:
当使用 分配异常时
as target
,它会在 except 子句的末尾清除。
使用装饰器
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()
Run Code Online (Sandbox Code Playgroud)