Psycopg2:退出包含 try/except 的“with”语句时连接未提交

bou*_*tta 5 python psycopg2 python-2.7

首先,我想说明我很清楚 psycopg 打开了一个需要提交才能发生数据库更新的事务。

但是,这里引用了有关提交的文档:

犯罪()

将任何挂起的事务提交到数据库。

默认情况下,Psycopg 在执行第一个命令之前打开一个事务:如果没有调用 commit(),任何数据操作的效果都将丢失。

连接也可以设置为“自动提交”模式:没有事务自动打开,命令立即生效。有关详细信息,请参阅事务控制。

在 2.5 版更改:如果在 with 语句中使用连接,则如果在 with 块中没有引发异常,则会自动调用该方法。

与回滚类似:

回滚()

回滚到任何挂起事务的开始。关闭连接而不首先提交更改将导致执行隐式回滚。

在 2.5 版更改:如果在 with 语句中使用连接,则在 with 块中引发异常时自动调用该方法。

然而,这似乎对我不起作用。也许我很挑剔,并且应该始终养成明确提交的习惯(但很高兴知道如果我忘记了它会发生回滚)。我想知道是否有人提出了同样的问题,或者我是否错误地使用了 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
Run Code Online (Sandbox Code Playgroud)

这不起作用。查询本身没有问题,因为我得到 : UPDATE 842518 作为预期的输出。但是,由于我的数据库未更新,因此显然未提交来自连接的更改。如果我添加

conn.commit()
Run Code Online (Sandbox Code Playgroud)

在 try 语句中它有效,但重点是避免这样做。

我的 psycopg2 版本是 2.6。

链接到文档

Ilj*_*ilä 9

在关闭时包装连接和游标对象很容易弄乱它们的上下文处理;他们自己就是上下文管理器。一个closing包装将只需要调用他们的close()退出方法。

close()在 with 块中使用游标时无需手动调用。这同样不适用于连接;只有交易在从 with-block 退出时结束。这是设计使然,因此您可以在多个 with 块中使用相同的连接:

请注意,与文件对象或其他资源不同,退出连接的 with 块不会关闭连接,而只会关闭与其关联的事务:连接可以在多个 with 语句中使用,并且每个 with 块都有效地包装在单独的交易

例如,您可以将连接包装closing在最外面的 with-block 中,然后在内部 with-blocks 中使用相同的连接进行事务处理等:

# 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:
        ...
Run Code Online (Sandbox Code Playgroud)