使用带有psycopg2的try / except或“with closing”?

时间:2012-09-26 18:39:41

标签: python postgresql psycopg2

我在Python中使用Psycopg2来访问PostgreSQL数据库。我很好奇使用with closing()模式创建和使用游标是否安全,或者我是否应该使用围绕查询的显式try/except。我的问题是关于插入或更新以及交易。

据我所知,所有Psycopg2查询都发生在一个事务中,并且由调用代码来提交或回滚事务。如果在with closing(...块内发生错误,是否发出回滚?在较旧版本的Psycopg2中,在close()上明确发布了回滚,但现在情况不再如此(请参阅http://initd.org/psycopg/docs/connection.html#connection.close)。

通过一个例子,我的问题可能更有意义。以下是使用with closing(...

的示例
with closing(db.cursor()) as cursor:
     cursor.execute("""UPDATE users                    
             SET password = %s, salt = %s
             WHERE user_id = %s""",
             (pw_tuple[0], pw_tuple[1], user_id))
     module.rase_unexpected_error()
     cursor.commit()

当module.raise_unexpected_error()引发错误时会发生什么?交易是否回滚?据我了解事务,我要么提交它们要么回滚它们。那么在这种情况下,会发生什么?

或者我可以这样写我的查询:

cursor = None
try:
    cursor = db.cursor()
    cursor.execute("""UPDATE users                    
            SET password = %s, salt = %s
            WHERE user_id = %s""",
            (pw_tuple[0], pw_tuple[1], user_id))
    module.rase_unexpected_error()
    cursor.commit()
except BaseException:
    if cursor is not None:
        cursor.rollback()
finally:
    if cursor is not None:
        cursor.close()

另外我应该提一下,我不知道Psycopg2的连接类cursor()方法是否会引发错误(文档没有说)所以安全性比抱歉更好,不是吗?

我应该使用哪种发布查询和管理交易的方法?

1 个答案:

答案 0 :(得分:6)

Your link to the Psycopg2 docs有点解释它,不是吗?

  

...请注意,首先关闭连接而不提交更改   导致任何挂起的更改被丢弃,就像ROLLBACK一样   执行(除非选择了不同的隔离级别:请参阅   set_isolation_level())。

     

在2.2版中更改:之前发布了显式ROLLBACK   Psycopg关闭()。该命令可能已发送到后端   不合适的时间,所以 Psycopg目前依赖于后端   隐含地放弃未提交的更改。一些中间件是众所周知的   虽然在a期间关闭连接时表现不正确   事务(当状态为STATUS_IN_TRANSACTION时),例如PgBouncer   报告一个不干净的服务器并丢弃该连接。为了避免这种情况   你可以确保用a终止交易的问题   在关闭之前提交()/ rollback()。

因此,除非您使用不同的隔离级别或使用PgBouncer,否则您的第一个示例应该可以正常工作。但是,如果您希望对事务中发生的事情进行更细粒度的控制,那么try / except方法可能是最好的,因为它与数据库事务状态本身并行。