Reputation: 469
I am implementing a database connector class in python. I will use the retry
decorator from tenacity library to retry the connection of database when it times out.
I want to pass the self.retry_count
and self.retry_interval
to the arguments in retry
decorator.
## etl_connect.py
from sqlalchemy import create_engine
import pymysql
import logging
from tenacity import *
class Connector():
def __init__(self, mode, conn_str, retry_count, retry_interval):
self.mode = mode
self.conn_str = conn_str
self.retry_count = retry_count
self.retry_interval = retry_interval
self.engine = None
self.conn = None
@retry(wait=wait_fixed(self.retry_interval), stop=stop_after_attempt(self.retry_count))
def mysql_connect(self):
logging.info('Connecting to mysql. (retry count=%d)' % (self.mysql_connect.retry.statistics['attempt_number']))
mysql_engine = create_engine(self.conn_str)
mysql_conn = mysql_engine.connect()
logging.info('Connected to mysql successfully with %d attempt(s).' % (self.mysql_connect.retry.statistics['attempt_number']))
return (mysql_engine, mysql_conn)
Now call the mysql_connect
function:
## call.py
from etl_connect import *
mysql_connector = Connector('mysql', 'mysql database string here', 5, 10)
engine, conn = mysql_connector.mysql_connect()
But it shows: NameError: name 'self' is not defined
.
Traceback (most recent call last):
File "call.py", line 5, in <module>
from etl_connect import *
File "/home/developer/ETL_modules/etl_connect.py", line 19, in <module>
class Connector():
File "/home/developer/ETL_modules/etl_connect.py", line 56, in Connector
@retry(wait=wait_fixed(self.retry_interval), stop=stop_after_attempt(self.retry_count))
NameError: name 'self' is not defined
Are there any ways that I can pass self.retry_count
& self.retry_interval
to the decorator?
Upvotes: 2
Views: 2726
Reputation: 123473
Assuming you can't easily redefine the tenacity retry
decorator, you could wrap it with one of your own that references the values in the Connector
instance.
Here's what I mean:
# Wrapper for tenacity retry decorator
def my_retry(func):
def wrapped(conn, *args, **kwargs):
tdecorator = retry(wait=wait_fixed(conn.retry_interval),
stop=stop_after_attempt(conn.retry_count))
decorated = tdecorator(func)
return decorated(conn, *args, **kwargs)
return wrapped
class Connector():
def __init__(self, mode, conn_str, retry_count, retry_interval):
self.mode = mode
self.conn_str = conn_str
self.retry_count = retry_count
self.retry_interval = retry_interval
self.engine = None
self.conn = None
@my_retry
def mysql_connect(self):
logging.info('Connecting to mysql. (retry count=%d)' % (self.mysql_connect.retry.statistics['attempt_number']))
mysql_engine = create_engine(self.conn_str)
mysql_conn = mysql_engine.connect()
logging.info('Connected to mysql successfully with %d attempt(s).' % (self.mysql_connect.retry.statistics['attempt_number']))
return (mysql_engine, mysql_conn)
Upvotes: 0
Reputation: 4392
If you don't access @retry
decorator and you prevent to edit it you can define a variable out of your class definition. Or you can define this base config in your setting's file then import it. Please look at this:
## etl_connect.py
from sqlalchemy import create_engine
import pymysql
import logging
from tenacity import *
base_config = {
'retry_count': 3,
'retry_interval': 30,
...
}
class Connector():
def __init__(self, mode, conn_str):
self.mode = mode
self.conn_str = conn_str
self.engine = None
self.conn = None
@retry(wait=wait_fixed(base_config['retry_interval']), stop=stop_after_attempt(base_config['retry_count']))
def mysql_connect(self):
logging.info('Connecting to mysql. (retry count=%d)' % (self.mysql_connect.retry.statistics['attempt_number']))
mysql_engine = create_engine(self.conn_str)
mysql_conn = mysql_engine.connect()
logging.info('Connected to mysql successfully with %d attempt(s).' % (self.mysql_connect.retry.statistics['attempt_number']))
return (mysql_engine, mysql_conn)
Or import from setting's file:
from sqlalchemy import create_engine
import pymysql
import logging
from tenacity import *
from settings import RETRY_COUNT
from settings import RETRY_INTERVAL
I know this way is solid but these options should define in your settings and no need to pass them every time you want make-instance of your class.
Upvotes: 0
Reputation: 531295
Instead of decorating the method, call retry
when you call the method.
## etl_connect.py
from sqlalchemy import create_engine
import pymysql
import logging
from tenacity import *
class Connector():
def __init__(self, mode, conn_str, retry_count, retry_interval):
self.mode = mode
self.conn_str = conn_str
self.retry_count = retry_count
self.retry_interval = retry_interval
self.engine = None
self.conn = None
def _mysql_connect(self):
logging.info('Connecting to mysql. (retry count=%d)' % (self.mysql_connect.retry.statistics['attempt_number']))
mysql_engine = create_engine(self.conn_str)
mysql_conn = mysql_engine.connect()
logging.info('Connected to mysql successfully with %d attempt(s).' % (self.mysql_connect.retry.statistics['attempt_number']))
return (mysql_engine, mysql_conn)
def mysql_connect(self):
d = retry(
wait=wait_fixed(self.retry_interval),
stop=stop_after_attempt(self.retry_count)
)
# One of these two should work, depending on how
# retry is actually defined.
return d(Connector._mysql_connect)(self)
# return d(self._mysql_connect)
Upvotes: 4
Reputation: 217
Unless the decorator (retry) is defined as part of the class (and is not static) then you cannot reference an object instance in it.
Upvotes: 0