Created
February 24, 2010 22:32
-
-
Save rmg/313956 to your computer and use it in GitHub Desktop.
Little retry loop wrappers (handling return codes and exceptions)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from functools import wraps | |
def retry(attempts, f): | |
""" | |
Returns a callable that will invoke @f() and return result, suppressing | |
exceptions up to @attempts times | |
""" | |
@wraps(f) | |
def wrapper(*args, **kwds): | |
hardfail = None | |
for i in range(attempts): | |
try: | |
return f(*args, **kwds) | |
except Exception as e: | |
hardfail = e | |
if __debug__: | |
print("Failed to execute {0} -> {1}\n".format(f, e)) | |
time.sleep(i) | |
raise hardfail | |
return wrapper | |
def retry_until(attempts, f, until): | |
""" | |
Retruns a callable that will call @f() until @until is returned or | |
@attempts has been exceeded. | |
""" | |
@wraps(f) | |
def wrapper(*args, **kwds): | |
hardfail = None | |
for i in range(attempts): | |
try: | |
# only want to capture the last exception if it was the cause | |
# of the failure | |
hardfail = None | |
if f(*args, **kwds) == until: | |
return True | |
except Exception as e: | |
hardfail = e | |
if __debug__: | |
print("Failed to execute {0} -> {1}\n".format(f, e)) | |
time.sleep(i) | |
if hardfail: | |
raise hardfail | |
return False | |
return wrapper | |
import os | |
# The original use case of retry_until was transient erros when unmounting filesystems that may be busy for a couple seconds | |
retry_until(5, os.system, 0)("umount /tmp/foo") | |
# Useless example | |
retry_until(5, os.system, 0)("ls /foobar") | |
# ls: cannot access foo: No such file or directory | |
# ls: cannot access foo: No such file or directory | |
# ls: cannot access foo: No such file or directory | |
# ls: cannot access foo: No such file or directory | |
# ls: cannot access foo: No such file or directory | |
# False | |
# The original use of retry was for retry_until cases that involve exceptions being thrown | |
retry(10, shutil.rmtree)("/tmp/foo") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment