WindowsError 关闭后移动 sqlite3 数据库
WindowsError moving sqlite3 database after closing
这是我的问题的一个简化示例:
import os
import sqlite3
with sqlite3.connect('test.db.temp') as db:
db.executescript('CREATE TABLE foo (bar);')
os.rename('test.db.temp', 'test.db')
输出:
> python test.py
Traceback (most recent call last):
File "test.py", line 7, in <module>
os.rename('test.db.temp', 'test.db')
WindowsError: [Error 32] The process cannot access the file because it is being used by another process
背景:我正在尝试以 "atomic" 方式创建数据库,最简单的方法是在临时位置创建数据库,然后移动它。
问题是连接对象的上下文管理器似乎不起作用。
这样操作:
db = sqlite3.connect('test.db.temp')
db.executescript('CREATE TABLE foo (bar);')
db.close()
os.rename('test.db.temp', 'test.db')
值得研究为什么它首先实现了 __enter__/__exit__
...
更新: 从这个 answer 看来 with
与 SQLite 一起使用时会执行事务,因此您的代码类似于:
db = sqlite3.connect('test.db.temp')
db.begin_transaction()
db.executescript('CREATE TABLE foo (bar);')
db.commit()
os.rename('test.db.temp', 'test.db')
所以重命名时数据库仍然明显打开。推荐的代码将类似于:
with contextlib.closing(sqlite3.connect('test.db.temp')) as db:
db.executescript('CREATE TABLE foo (bar);')
os.rename('test.db.temp', 'test.db')
根据documentation,executescript创建游标对象。我猜光标对象不会立即被销毁。尝试在上下文管理器中显式创建游标:
with sqlite3.connect('test.db.temp') as db:
cur = db.cursor()
cur.execute('CREATE TABLE foo (bar);')
这是我的问题的一个简化示例:
import os
import sqlite3
with sqlite3.connect('test.db.temp') as db:
db.executescript('CREATE TABLE foo (bar);')
os.rename('test.db.temp', 'test.db')
输出:
> python test.py
Traceback (most recent call last):
File "test.py", line 7, in <module>
os.rename('test.db.temp', 'test.db')
WindowsError: [Error 32] The process cannot access the file because it is being used by another process
背景:我正在尝试以 "atomic" 方式创建数据库,最简单的方法是在临时位置创建数据库,然后移动它。
问题是连接对象的上下文管理器似乎不起作用。
这样操作:
db = sqlite3.connect('test.db.temp')
db.executescript('CREATE TABLE foo (bar);')
db.close()
os.rename('test.db.temp', 'test.db')
值得研究为什么它首先实现了 __enter__/__exit__
...
更新: 从这个 answer 看来 with
与 SQLite 一起使用时会执行事务,因此您的代码类似于:
db = sqlite3.connect('test.db.temp')
db.begin_transaction()
db.executescript('CREATE TABLE foo (bar);')
db.commit()
os.rename('test.db.temp', 'test.db')
所以重命名时数据库仍然明显打开。推荐的代码将类似于:
with contextlib.closing(sqlite3.connect('test.db.temp')) as db:
db.executescript('CREATE TABLE foo (bar);')
os.rename('test.db.temp', 'test.db')
根据documentation,executescript创建游标对象。我猜光标对象不会立即被销毁。尝试在上下文管理器中显式创建游标:
with sqlite3.connect('test.db.temp') as db:
cur = db.cursor()
cur.execute('CREATE TABLE foo (bar);')