Следующая, кажется, делать то, что вы описали:
def retry_if_exception(exception, max_retries=2):
def _retry_if_exception(method_fn):
# method_fn is the function that gives rise
# to the method that you've decorated,
# with signature (slf, foo)
from functools import wraps
def method_deco(slf, foo):
tries = 0
while True:
try:
return method_fn(slf, foo)
except exception:
tries += 1
if tries > max_retries:
raise
return wraps(method_fn)(method_deco)
return _retry_if_exception
Вот пример этого в использовании:
d = {}
class Foo():
def usually_raise_KeyError(self):
print("d[17] = %s" % d[17])
foo1 = Foo()
class A():
@retry_if_exception(KeyError, max_retries=2)
def something_that_sometimes_fails(self, foo):
print("About to call foo.usually_raise_KeyError()")
foo.usually_raise_KeyError()
a = A()
a.something_that_sometimes_fails(foo1)
Это дает:
About to call foo.usually_raise_KeyError()
About to call foo.usually_raise_KeyError()
About to call foo.usually_raise_KeyError()
Traceback (most recent call last):
File " ......... TrapRetryDeco.py", line 39, in <module>
a.something_that_sometimes_fails(foo1)
File " ......... TrapRetryDeco.py", line 15, in method_deco
return method_fn(slf, foo)
File " ......... TrapRetryDeco.py", line 36, in something_that_sometimes_fails
foo.usually_raise_KeyError()
File " ......... TrapRetryDeco.py", line 28, in usually_raise_KeyError
print("d[17] = %s" % d[17])
KeyError: 17
Я полагаю, что по «2 повторения» вы подразумеваете, что операция будет предпринята 3 раза. В вашем примере есть несколько осложнений, которые могут затенять базовую настройку: Кажется, что вам нужен декоратор метода, так как первым параметром функции/метода является «self»; однако этот метод сразу же передаёт какой-нибудь плохой метод его параметра foo. Я сохранил эти осложнения :)
Принято для обертываний –