4

我是 python 新手。我正在尝试创建一个重试装饰器,当应用于函数时,它将继续重试,直到满足某些条件(为简单起见,说重试 10 次)。

def retry():
    def wrapper(func):
        for i in range(0,10):
            try:
                func()
                break
            except:
               continue
    return wrapper

现在它将重试任何异常。如何更改它以使其重试特定异常。例如,我想像这样使用它:

@retry(ValueError, AbcError)
def myfunc():
    //do something

我只想myfunc重试它会抛出ValueErrorAbcError.

4

3 回答 3

10

You can supply a tuple of exceptions to the except .. block to catch:

from functools import wraps

def retry(*exceptions, **params):
    if not exceptions:
        exceptions = (Exception,)
    tries = params.get('tries', 10)

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kw):
            for i in range(tries):
                try:
                    return func(*args, **kw)
                except exceptions:
                    pass
        return wrapper
    return decorator

The catch-all *exceptions parameter will always result in a tuple. I've added a tries keyword as well, so you can configure the number of retries too:

@retry(ValueError, TypeError, tries=20)
def foo():
    pass

Demo:

>>> @retry(NameError, tries=3)
... def foo():
...     print 'Futzing the foo!'
...     bar
... 
>>> foo()
Futzing the foo!
Futzing the foo!
Futzing the foo!
于 2013-08-07T11:18:13.473 回答
2
from functools import wraps

class retry(object):
    def __init__(self, *exceptions):
        self.exceptions = exceptions

    def __call__(self, f):
        @wraps(f) # required to save the original context of the wrapped function
        def wrapped(*args, **kwargs):
            for i in range(0,10):
                try:
                    f(*args, **kwargs)
                except self.exceptions:
                    continue
        return wrapped

用法:

@retry(ValueError, Exception)
def f():
    print('In f')
    raise ValueError


>>> f()
In f
In f
In f
In f
In f
In f
In f
In f
In f
In f
于 2013-08-07T11:22:51.510 回答
1

You can check the error class:

except Exception as e:
    for et in error_types: #(or args)
        if isinstance(e, et):
            continue
    raise e #re-raise
于 2013-08-07T11:18:35.217 回答