Psycopg2:退出包含 try/except 的 'with' 语句时连接未提交
Psycopg2: connection not committing when exiting 'with' statement containing a try/except
首先,我想声明我很清楚 psycopg 打开一个事务,需要提交才能进行数据库更新。
但是这里引用了关于提交的文档:
commit()
Commit any pending transaction to the database.
By default, Psycopg opens a transaction before executing the first command: if commit() is not called, the effect of any data manipulation will be lost.
The connection can be also set in “autocommit” mode: no transaction is automatically open, commands have immediate effect. See Transactions control for details.
Changed in version 2.5: if the connection is used in a with statement, the method is automatically called if no exception is raised in the with block.
回滚也类似:
rollback()
Roll back to the start of any pending transaction. Closing a connection without committing the changes first will cause an implicit rollback to be performed.
Changed in version 2.5: if the connection is used in a with statement, the method is automatically called if an exception is raised in the with block.
然而这似乎对我不起作用。也许我很挑剔,并且应该始终养成显式提交的习惯(但是如果我忘记它会发生回滚,那就太好了)。我想知道是否有人遇到了同样的问题,或者我是否错误地使用了我的 with 语句。
我的代码如下所示:
import psycopg2
from contextlib import closing
with closing(psycopg2.connect(
#conn params
) as conn, \
closing(conn.cursor()) as cur:
try:
sql = #query
cur.execute(sql)
output = cur.statusmessage
print output
except Exception, e :
print "Error message : {}".format(e)
raise
这行不通。查询本身没有问题,因为我得到:
更新 842518
正如预期的那样输出。但是,由于我的数据库未更新,因此显然未提交来自连接的更改。
如果我添加
conn.commit()
在 try 语句中它有效,但重点是避免这样做。
我的 psycopg2 版本是 2.6。
在关闭时包装连接和游标对象很可能会扰乱它们的上下文处理; they are context managers them selves。 closing
包装器只会在退出时调用它们的 close()
方法。
在 with 块中使用游标时无需手动调用 close()
。这同样不适用于连接;只有事务在退出 with 块时结束。这是设计使然,因此您可以在多个 with 块中使用相同的连接:
Note that, unlike file objects or other resources, exiting the connection’s with block doesn’t close the connection but only the transaction associated with it: a connection can be used in more than a with statement and each with block is effectively wrapped in a separate transaction
例如,您可以将 closing
中的连接包装在最外层的 with-block 中,然后在内部 with-block 中使用相同的连接进行事务处理等:
# This'll handle closing the connection
with closing(psycopg2.connect(...)) as conn:
# This'll handle the transaction and closing the cursor
with conn, conn.cursor() as cur:
...
首先,我想声明我很清楚 psycopg 打开一个事务,需要提交才能进行数据库更新。
但是这里引用了关于提交的文档:
commit()
Commit any pending transaction to the database.
By default, Psycopg opens a transaction before executing the first command: if commit() is not called, the effect of any data manipulation will be lost.
The connection can be also set in “autocommit” mode: no transaction is automatically open, commands have immediate effect. See Transactions control for details.
Changed in version 2.5: if the connection is used in a with statement, the method is automatically called if no exception is raised in the with block.
回滚也类似:
rollback()
Roll back to the start of any pending transaction. Closing a connection without committing the changes first will cause an implicit rollback to be performed.
Changed in version 2.5: if the connection is used in a with statement, the method is automatically called if an exception is raised in the with block.
然而这似乎对我不起作用。也许我很挑剔,并且应该始终养成显式提交的习惯(但是如果我忘记它会发生回滚,那就太好了)。我想知道是否有人遇到了同样的问题,或者我是否错误地使用了我的 with 语句。
我的代码如下所示:
import psycopg2
from contextlib import closing
with closing(psycopg2.connect(
#conn params
) as conn, \
closing(conn.cursor()) as cur:
try:
sql = #query
cur.execute(sql)
output = cur.statusmessage
print output
except Exception, e :
print "Error message : {}".format(e)
raise
这行不通。查询本身没有问题,因为我得到: 更新 842518 正如预期的那样输出。但是,由于我的数据库未更新,因此显然未提交来自连接的更改。 如果我添加
conn.commit()
在 try 语句中它有效,但重点是避免这样做。
我的 psycopg2 版本是 2.6。
在关闭时包装连接和游标对象很可能会扰乱它们的上下文处理; they are context managers them selves。 closing
包装器只会在退出时调用它们的 close()
方法。
在 with 块中使用游标时无需手动调用 close()
。这同样不适用于连接;只有事务在退出 with 块时结束。这是设计使然,因此您可以在多个 with 块中使用相同的连接:
Note that, unlike file objects or other resources, exiting the connection’s with block doesn’t close the connection but only the transaction associated with it: a connection can be used in more than a with statement and each with block is effectively wrapped in a separate transaction
例如,您可以将 closing
中的连接包装在最外层的 with-block 中,然后在内部 with-block 中使用相同的连接进行事务处理等:
# This'll handle closing the connection
with closing(psycopg2.connect(...)) as conn:
# This'll handle the transaction and closing the cursor
with conn, conn.cursor() as cur:
...