python sqlite 3:回滚保存点失败

时间:2010-02-02 08:06:14

标签: python sqlite

def rollback_savepoint(self):
    try:
        self.db.execute("rollback to savepoint pt;")
    except:
        print "roll back to save point failed"
    else:
        print "Roll back to save point. Done"

在上面的代码片段中,它说“回滚到保存点失败”。 出了什么问题?

编辑: 我更改了如下所示的代码并收到错误消息

self.db.execute("savepoint pt;")
print "Save point created"

self.cursor.execute("insert into STK values(33)")
self.db.execute("rollback to savepoint pt;")

错误

Save point created
Traceback (most recent call last):
  File "open_db.py", line 77, in <module>
    obj1.save_point()
  File "open_db.py", line 63, in save_point
    self.db.execute("rollback to savepoint pt;")
sqlite3.OperationalError: no such savepoint: pt

1 个答案:

答案 0 :(得分:4)

不要捕获您未处理的异常。让它提升,这样你就可以得到有用的错误信息和追溯。

示例:

>>> c.execute('rollback to savepoint pt;')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sqlite3.OperationalError: no such savepoint: pt

从回溯中我可以知道错误是没有pt个保存点。我不知道你的错是什么,因为你隐藏的信息可以帮助你。捕获所有错误并打印一些“失败”消息是愚蠢的 - 回溯更有用并更好地解释问题。


修改 你的代码并不是一个易于运行的测试用例,但通过阅读它我能够自己编写一些代码来重现这个问题。我无法准确解释到底发生了什么,但我找到了一种方法让它发挥作用 - 与how sqlite3 module deals with transactions相关。

这是我完整的,可运行的例子:

import sqlite3
from tempfile import NamedTemporaryFile as NF
import os

f = NF(suffix='.db', delete=False).name

db = sqlite3.connect(f)

try:
    db.execute('CREATE TABLE foo (id INTEGER PRIMARY KEY, data VARCHAR)')
    db.isolation_level = None

    db.execute('INSERT INTO foo (data) values (?)', ('hello',))
    db.execute('INSERT INTO foo (data) values (?)', ('world',))

    db.execute("savepoint pt;")
    db.execute('INSERT INTO foo (data) values (?)', ('bah',))
    db.execute('INSERT INTO foo (data) values (?)', ('goodbye world',))
    db.execute("rollback to savepoint pt;")

    db.execute('INSERT INTO foo (data) values (?)', ('peace',))

    assert list(db.execute('select * from foo')) == [(1, 'hello'),
                                                     (2, 'world'),
                                                     (3, 'peace')]
finally:
    db.close()
    os.remove(f)

使其有效的行是db.isolation_level = None。如果你把它评论出来,它会像你的错误一样中断。我尝试使用所有记录的值“DEFERRED”,“IMMEDIATE”和“EXCLUSIVE”,都以错误结束。