关闭后WindowsError移动sqlite3数据库

时间:2015-01-19 20:07:24

标签: python windows sqlite

以下是我的问题的简化示例:

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

背景:我正在尝试以“原子”方式创建数据库,最简单的方法是在临时位置创建数据库,然后移动它。

2 个答案:

答案 0 :(得分:4)

问题是连接对象的上下文管理器似乎无法工作。

这种方式有效:

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')

答案 1 :(得分:0)

根据documentation executioncript 会创建一个游标对象。我猜测光标对象不会立即被销毁。尝试在上下文管理器中显式创建游标:

with sqlite3.connect('test.db.temp') as db:
    cur = db.cursor()
    cur.execute('CREATE TABLE foo (bar);')