A while ago I asked this question Memoizing decorator that can retry and then promptly forgot about it. I more recently saw Python decorator for retrying w/exponential backoff and wanted to add backoff, but figured I should improve what I already have first. I have taken some of the suggestions of the original, but really I've just completely reimagined it (and if I do say so myself, rather cleverly too). My biggest issue with this is that I'm not sure that my current distinction between "exceptions that get suppressed but not remembered" and "exceptions that get remembered" seems like it might be a bit confusing - is there a friendlier interface here?
import functools
from types import MappingProxyType as FrozenDict
class Memoizer:
def __init__(self, retry_times=0, suppressed_exceptions=tuple(), capture_exceptions=False):
self.retry = retry
self.retry_times = retry_times
self.suppressed_exceptions = suppressed_exceptions
self.capture_exceptions = capture_exceptions
def __call__(self, function):
d = {}
@functools.wraps(function)
def wrapper(*args, **kwargs, __forget=False):
key = (args, FrozenDict(kwargs))
if key not in d or __forget:
i = self.retry_times
while i > 1:
try:
d[key] = function(*args, **kwargs)
except self.suppressed_exceptions:
continue
except Exception as e:
if self.capture_exceptions:
d[key] = e
break
raise
else:
break
i -= 1
else:
# If we didn't already break out, the last attempt shouldn't suppress exceptions
d[key] = function(*args, **kwargs)
return d[key]
return wrapper
d
defined inside the function? I think this should erase its contents each time the function is called? I am confused as to why this works... \$\endgroup\$d
is changed each time, but the individualwrapper
functions are closures overd
, so they maintain their own copies. \$\endgroup\$d
defined in__init__
if you do want to set it to empty just once? \$\endgroup\$m = Memoizer()
you'd share the cache between functions with your suggestion, where this way the cache is made when you pass the functionfn = Memoizer()(fn)
. \$\endgroup\$