Python:对一个函数尝试 3 次,直到全部失败

Mai*_*Mai 2 python error-handling design-patterns

我在Python2.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)

是否有更好的片段可以实现相同的用例?

jon*_*rpe 5

这是一种可能的方法:

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)

这是因为errtry语句结束时清除了;根据文档

当使用 分配异常时as target,它会在 except 子句的末尾清除。


pow*_*rfj 5

使用装饰器

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)