Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I pass an exception as an argument to a function in python?

I am new to python. I am trying to create a retry decorator that, when applied to a function, will keep retrying until some criteria is met (for simplicity, say retry 10 times).

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

Now that will retry on any exception. How can I change it such that it retries on specific exceptions. e.g, I want to use it like:

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

I want myfunc to be retried only of it throws ValueError or AbcError.

like image 694
Hari Menon Avatar asked Dec 11 '22 12:12

Hari Menon


2 Answers

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!
like image 168
Martijn Pieters Avatar answered Apr 27 '23 06:04

Martijn Pieters


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

Usage:

@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
like image 45
Zaur Nasibov Avatar answered Apr 27 '23 06:04

Zaur Nasibov