Try/Except Every Method in Class?

python

Solution

Decorators are perfect for this. You can decorate each relevant method with a decorator like this one:

(Note using recursion for retries is probably not a great idea ...)

def Http500Resistant(func):
    num_retries = 5
    @functools.wraps(func)
    def wrapper(*a, **kw):
        sleep_interval = 2
        for i in range(num_retries):
            try:
                return func(*a, **kw)
            except apiclient.errors.HttpError, e:
                if e.resp.status == 500 and i < num_retries-1:
                    sleep(sleep_interval)
                    sleep_interval = min(2*sleep_interval, 60)
                else:
                    raise e    
    return wrapper

class A(object):

    @Http500Resistant
    def f1(self): ...

    @Http500Resistant
    def f2(self): ...

To apply the decorator to all methods automatically, you can use yet-another-decorator, this time, decorating the class:

import inspect
def decorate_all_methods(decorator):
    def apply_decorator(cls):
        for k, f in cls.__dict__.items():
            if inspect.isfunction(f):
                setattr(cls, k, decorator(f))
        return cls
    return apply_decorator

and apply like this:

@decorate_all_methods(Http500Resistant)
class A(object):
    ...

Or like:

class A(object): ...
A = decorate_all_methods(Http500Resistant)(A)

Problem

I'm currently working with Google's BigQuery API, which when called, occasionally gives me: ``` apiclient.errors.HttpError: <HttpError 500 when requesting https://www.googleapis.com/bigquery/v2/projects/some_job?alt=json returned "Unexpected. Please try again."> ``` It's kind of a silly thing to return, but anyway, when I get this for any method called, I'd want to just sleep a second or two and then try again. Basically, I'd want to wrap every method with something like: ``` def new_method try: method() except apiclient.errors.HttpError, e: if e.resp.status == 500: sleep(2) new_method() else: raise e ``` What's a good way of doing this? I don't want to explicitly redefine every method in the class. I just want to apply something automatically to every method in the class, so I'm covered for the future. Ideally, I'd take a class object, o, and make a wrapper around it that redefines every method in the class with this try except wrapper so I get some new object, p, that automatically retries when it gets a 500 error.

Original source

Related problems