Python 3.6.0的sqlite3模块无法执行VACUUM语句
Python 3.6.0的sqlite3模块存在一个bug(见issue 28518),无法执行VACUUM语句。Python 3.6.1已经修复这个bug。
一执行就出现异常:
Traceback (most recent call last):
File "D:\desktop\cannot_vacuum.py", line 25, in <module>
conn.execute('VACUUM')
sqlite3.OperationalError: cannot VACUUM from within a transaction
这是因为在真正执行VACUUM之前,Python 3.6.0的sqlite3模块(自作主张地)添加了一条BEGIN语句创建了一个事务,而VACUUM不能在事务中执行。
在Python 3.6.0,要想让程序正常运行,需要在connect时设置isolation_level参数为None,如下:
conn = sqlite3.connect('test.db', isolation_level=None)
或者这样做:
conn = sqlite3.connect('test.db')
conn.isolation_level = None
查看文档和源码,isolation_level=None的作用:sqlite3模块在开始执行某些SQL语句之前,不再(智能地)自动BEGIN一个事务、或自动COMMIT上一个事务。用户须手动BEGIN一个事务、手动COMMIT之前的修改。
此时(isolation_level=None)程序完全遵照SQLite引擎的行为:在事务以外执行一条SQL语句之后,会立刻COMMIT修改。
尽管sqlite3模块默认的“傻瓜模式”在绝大多数情况下工作良好,个人还是推荐尽量使用isolation_level=None,原因有三:
- 在个别复杂情况下,傻瓜模式有陷阱,不了解的人容易陷进去。见issue 10740的讨论。
- sqlite3模块更透明,sqlite3引擎更简洁。喜欢这种风格。
- 同一代码在所有版本的Python 3都行得通。
posted on 2016-12-23 18:10 animalize 阅读(2329) 评论(0) 编辑 收藏 举报