共享txpostgres连接p

2024-06-09 14:17:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我们有一个RESTful(-ish)twisted应用程序,它使用txpostgres访问postgres数据库。目前,每次客户机ping服务器进行db调用时,我们都会生成新的txpostgres.Connection实例。这是低效的,并导致我们的数据库迅速变得不堪重负。我一直在尝试使用txpostgres.ConnectionPool来代替它,但是遇到了麻烦。现在我有一个看起来像这样的东西:

class DBTester(object):
    def __init__(self):
        self.cfg = load_config('local')  # load the db settings from a JSON file
        self.pool = ConnectionPool(None, min=1, **self.cfg) # create the pool

    @defer.inlineCallbacks
    def get_pool(self):
        yield self.pool.start()
        defer.returnValue(self.pool)


class DBT(object):
    def __init__(self):
        self.db = DBTester()

    @defer.inlineCallbacks
    def t(self):
        conn = yield self.db.get_pool()
        res = yield conn.runQuery('select * from clients')
        println('DBT.t result: {}'.format(res))


if __name__ == "__main__":
    dbt = DBT()
    dbt.t()
    dbt.t()

    reactor.run()

问题是pool.start()调用的时间。如果我把它放进DBTester.__init__,我得到psycopg2.OperationalError: asynchronous connection attempt underway。如果我把它放在DBTester.get_pool中,一个db.t()调用起作用,而另一个(s)则失败,并返回{}。我已经挣扎了一整天了,一直没能破解它,也没能在网上找到很多东西。在

我真的只需要一个指向如何使用ConnectionPool的最小示例的指针。有什么建议吗?在


Tags: self数据库dbgetinitdefdeferdbt
2条回答

听起来你的问题不在于txpostgres,而在于twisted和异步的思维方式。在

异常.AttributeError:“NoneType”对象没有属性“runQuery”表示: 在建立连接之前,您试图在数据库之后抛出SQL查询。太蠢了!所以现在我想我会抛出一个异常,让亲爱的用户知道这是多么疯狂。在

所以,如果你有

pool = ConnectionPool(None, min=1)
d1 = pool.start()
d2 = pool.runQuery('select tablename from pg_tables')

这段代码在反应堆中产生了两个延迟。只有调度算法知道先执行哪一个,如果是d2,则会发生错误。在

txpostgres.txpostgres.AlreadyConnected是指: 很好的自我解释,启动一个已经启动的池是没有意义的。在

psycopg2.operational错误:正在进行的异步连接尝试意味着:
当您开始执行SQL语句时,我正在设置一个很好的异步数据库连接。数据库连接还没有准备好,因此sql查询没有执行,这让我很难过。我想我会抛出一个操作错误,这样亲爱的用户就知道该语句失败了。在

好的,所以我们需要一种方法来确保在我们在数据库之后抛出sql查询之前建立了连接。下面是一个使用回调来实现这一点的代码示例。在

^{pr2}$

希望这有帮助。在

我不知道这是否算是最佳实践,但我们要做的是:

## dbutil.py
class DBConnection(object):
    def __init__(self, cfg_name):
        self.cfg_name = cfg_name
        self.cfg = self.load_config(self.cfg_name)
        self.pool = txpostgres.ConnectionPool(None, min=5, **self.cfg)

    @staticmethod
    def load_config(name):
        with open('config.json') as json_file:
            cfg = json.load(json_file)
        return cfg.get(name)

    @defer.inlineCallbacks
    def get_pool(self):
        try:
            yield self.pool.start()
        except txpostgres.AlreadyConnected:
            pass
        defer.returnValue(self.pool)


@defer.inlineCallbacks
def db_factory(cfg_name):
    db = DBConnection(cfg_name)
    db.pool = yield db.get_pool()
    defer.returnValue(db)


## basehandler.py
def __init__(self, name=None, db=None):
    resource.Resource.__init__(self)
    self.name = name
    self.db = db
    self.pool = self.db.pool

@defer.inlineCallbacks
def runQuery(self, *args, **kwargs):
    res = yield self.pool.runQuery(*args, **kwargs)
    defer.returnValue(res)


## server.py
@defer.inlineCallbacks
def init_site(db):
    db = yield db_factory(db)
    root = RootURLHandler(db)
    reactor.listenTCP(SERVER_PORT, site)

def main(db):
    log.startLogging(LogFile('server.log', '.', maxRotatedFiles=5))
    init_site(db)
    reactor.run()

关键,也许并不奇怪,是使站点初始化延迟取决于数据库的东西通过。在

相关问题 更多 >