【问题标题】:Psycopg2: connection not committing when exiting 'with' statement containing a try/exceptPsycopg2:退出包含 try/except 的“with”语句时连接未提交
【发布时间】:2017-01-05 17:48:04
【问题描述】:

首先我要声明,我很清楚 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

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

conn.commit()

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

我的 psycopg2 版本是 2.6。

Link to doc

【问题讨论】:

  • 只是一种预感,但是将连接和游标对象包装在closing 中会扰乱它们的上下文处理;他们自己就是上下文管理器。 closing 包装器只会在退出时调用它们的 close() 方法。
  • @IljaEverilä 尝试删除 closing,它确实有效。虽然现在我觉得我应该手动调用conn.close()cur.close()。随时发表您的评论作为我会接受的答案

标签: python python-2.7 psycopg2


【解决方案1】:

在关闭时包装连接和游标对象会扰乱它们的上下文处理; they are context managers them selvesclosing 包装器只会在退出时调用它们的 close() 方法。

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

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

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

# 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:
        ...

【讨论】:

  • 很好的答案!我真的很喜欢你使用最外层的 with-block 的想法。虽然在我的情况下,我不需要在多个 with 块中使用连接,所以我只是决定在 finally 块中关闭连接。
猜你喜欢
  • 2021-08-05
  • 2011-04-08
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
  • 1970-01-01
  • 2018-02-24
相关资源
最近更新 更多