4

Tried this in the retrying and tenacity python libraries to no avail.

Retries are typically used with a decorator, for example as shown in metacode below:

class FooBar:

   @retry(attempts=3)
   def dosomething():
      ...

I want the retry parameters to be configurable on the class

class FooBar:
   def __init__(retries=0):
       self.retries = retries

   @retry(attempts=self.retries)
   def dosomething():
      ...

Obviously this will break because the decorator cannot accedss object attributes (ie. cannot access self). So figured this would work:

def dosomething():
   with retry(attempts=self.retries):
       ...

But neither library allows for retry to be called in a with block

>  with retry():
E  AttributeError: __enter__

What is the preferred way to wrap retry logic with dynamic parameters?

Adam Hughes
  • 14,601
  • 12
  • 83
  • 122
  • May I ask... What is tenacity? This is the only question with it, so I presume you have created it. – cs1349459 Jul 06 '20 at 20:44
  • I have not created tenacity - it is a fork of the `retrying` library in python which apparently has no longer been in devleopment since 2016 and had bugs. I've seen `tenacity` and `backoff` listed as alternatives in related threads. I created the tag just now since its been mentioned in a few different threads at least. – Adam Hughes Jul 06 '20 at 20:49

2 Answers2

3

You needn't use deorators with the @ syntax - they can also be used as functions.

from tenacity import retry, stop_after_attempt

class CustomClass:
    def __init__(self, retries):
        decorator = retry(stop=stop_after_attempt(retries), reraise=True)
        self.method_with_retry = decorator(self.method)
    
    def method(self, x):
        print('Trying...')
        if x % 2:
            raise ValueError
        return x

CustomClass(3).method_with_retry(11)
bbayles
  • 4,389
  • 1
  • 26
  • 34
1

Nested function can help this:

class FooBar:
   def __init__(retries=0):
       self.retries = retries

   def dosomething():
       @retry(attempts=self.retries)
       def _dosomething():
          ...
       return _dosomething()
정도유
  • 559
  • 4
  • 6