Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 装饰中的自我参照_Python_Python 3.x_Python Decorators_Python Tenacity - Fatal编程技术网

Python 装饰中的自我参照

Python 装饰中的自我参照,python,python-3.x,python-decorators,python-tenacity,Python,Python 3.x,Python Decorators,Python Tenacity,我正在用python实现一个数据库连接器类。我将使用韧性库中的retrydecorator在数据库连接超时时重试连接 我想将self.retry\u count和self.retry\u interval传递给retry装饰器中的参数 ## etl_connect.py from sqlalchemy import create_engine import pymysql import logging from tenacity import * class Connector():

我正在用python实现一个数据库连接器类。我将使用韧性库中的
retry
decorator在数据库连接超时时重试连接

我想将
self.retry\u count
self.retry\u interval
传递给
retry
装饰器中的参数

## 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)
现在调用
mysql\u connect
函数:

## call.py
from etl_connect import *
mysql_connector = Connector('mysql', 'mysql database string here', 5, 10)
engine, conn = mysql_connector.mysql_connect()
但它显示:
name错误:未定义名称“self”

回溯(最近一次呼叫最后一次):
文件“call.py”,第5行,在
从etl_连接导入*
文件“/home/developer/ETL_modules/ETL_connect.py”,第19行,在
类连接器():
文件“/home/developer/ETL_modules/ETL_connect.py”,第56行,在连接器中
@重试(等待=等待\u固定(自重试间隔),停止=尝试后停止(自重试计数))
NameError:未定义名称“self”

有没有什么方法可以将self.retry\u count&
self.retry\u interval
传递给装饰器?

除非装饰器(retry)被定义为类的一部分(并且不是静态的),否则您不能引用其中的对象实例。

而不是装饰方法,调用方法时,请调用
重试

## 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)

如果您不访问
@retry
decorator并阻止对其进行编辑,则可以从类定义中定义一个变量。或者,您可以在设置的文件中定义此基本配置,然后导入它。请看这个:

## 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)
或从设置的文件导入:

from sqlalchemy import create_engine
import pymysql
import logging
from tenacity import *

from settings import RETRY_COUNT
from settings import RETRY_INTERVAL

我知道这种方法很可靠,但这些选项应该在您的设置中定义,并且无需在每次创建类实例时都传递它们。

假设您无法轻松重新定义韧性
重试
装饰器,您可以使用自己的一个选项来包装它,该选项引用
连接器
实例中的值

我的意思是:

# 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)

答案如下:请注意,答案假设您正在编写装饰程序;如果要导入
retry
,则需要定义自己的包装器。这是否回答了您的问题?这对我有用。你能解释一下为什么需要“(self)”吗?你说的是哪一个
self
?很抱歉没有澄清--mysql\u connect的return语句中的
(self)
。在这两种情况下,
\u mysql\u connect
都是一个实例方法,因此需要在
Connector
的实例上调用。您是显式地传递它,还是将绑定方法传递给
retry
,取决于
retry
(在原始问题中未定义)是采用零参数还是1参数可调用。