Quote __exit__ ,
If an exception is thrown and the method wants to suppress the exception (i.e., prevent its propagation), it should return the true value . Otherwise, the exception will usually be processed after exiting this method.
By default, if you do not return a value explicitly from a function, Python will return None , which is a false value. In your case, __exit__ returns None , and so the exception may go through __exit__ .
So return a true value like
class retry(object): def __init__(self, retries=0): ... def __enter__(self): ... def __exit__(self, exc_type, exc_val, traceback): print 'Attempts', self.attempts print exc_type, exc_val return True
the conclusion will be
Attempts 1 <type 'exceptions.NameError'> name 'ok' is not defined
If you want to have a snooze function, you can implement this with a generator, like
def retry(retries=3): left = {'retries': retries} def decorator(f): def inner(*args, **kwargs): while left['retries']: try: return f(*args, **kwargs) except NameError as e: print e left['retries'] -= 1 print "Retries Left", left['retries'] raise Exception("Retried {} times".format(retries)) return inner return decorator @retry(retries=3) def func(): print ok func()
source share