使用装饰器通过psycopg2进行数据库访问

时间:2015-09-12 09:32:58

标签: python postgresql psycopg2

我正在构建一个在Postgresql数据库中进行大部分计算的模型(出于性能原因)。看起来有点像这样:

def sql_func1(conn):
    # prepare some data, crunch some number, etc.
    curs = conn.cursor()
    curs.execute("SOME SQL COMMAND")
    curs.commit()
    curs.close()

if __name__ == "__main__":
    connection = psycopg2.connect(dbname='name', user='user', password='pass', host='localhost', port=1234)
    sql_func1(conn)
    sql_func2(conn)
    sql_func3(conn)
    connection.close()

该脚本使用大约30个单独的函数,如sql_func1。显然,在每个函数中始终管理连接和游标有点尴尬。因此我开始使用描述here的装饰器。现在我可以简单地用装饰器sql_func1包裹@db_connect并从那里传递连接。但是,这意味着我一直在打开和关闭连接,这也不是好习惯。 psycopg2 FAQ说:

  

创建连接可能很慢(想想基于TCP的SSL),所以最好   实践是创建单个连接并保持打开状态   需要。经常回滚或提交也是一种好习惯   (即使在单个SELECT语句之后)以确保后端是   从未离开过“闲置交易”。另见psycopg2.pool for   轻量级连接池。

请你给我一些见解,这对我来说是理想的做法。我是否应该使用通过cursor对象而不是connection的装饰器?如果是这样,请提供装饰器的代码示例。由于我对编程很陌生,如果您认为我的整体方法有误,请让我知道。

1 个答案:

答案 0 :(得分:0)

如何将连接存储在全局变量中而不在finally块中关闭它?像这样的东西(根据你链接的例子):

cnn = None
def with_connection(f):

    def with_connection_(*args, **kwargs):
        global cnn
        if not cnn:
            cnn = psycopg.connect(DSN)
        try:
            rv = f(cnn, *args, **kwargs)
        except Exception, e:
            cnn.rollback()
            raise
        else:
            cnn.commit() # or maybe not        
        return rv

    return with_connection_