我正在构建一个在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
的装饰器?如果是这样,请提供装饰器的代码示例。由于我对编程很陌生,如果您认为我的整体方法有误,请让我知道。
答案 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_