从单独的文件连接到SQLite内存数据库(Python)

时间:2018-07-21 12:17:10

标签: python sqlite

我正在构建的应用程序将需要一个单独的sqlite内存数据库,该数据库需要访问单独的例程和线程。我很难做到这一点。

我了解:

file:my_db?mode=memory&cache=shared', uri=True

应该创建一个可以通过单独的连接进行修改和访问的内存数据库。

这是我的测试,返回错误: “ sqlite3.OperationalError:没有这样的表:my_table”

下面的代码另存为“ test_create.py”:

import sqlite3

def create_a_table():
    db = sqlite3.connect('file:my_db?mode=memory&cache=shared', uri=True)
    cursor = db.cursor()

    cursor.execute('''
        CREATE TABLE my_table(id INTEGER PRIMARY KEY, some_data TEXT)
    ''')

    db.commit()
    db.close()

上面的代码在单独的文件中导入到下面的代码中:

import sqlite3
import test_create

test_create.create_a_table()
db = sqlite3.connect('file:my_db')
cursor = db.cursor()

# add a row of data
cursor.execute('''INSERT INTO my_table(some_data) VALUES(?)''', ("a bit of data",))
db.commit()

以上代码工作正常,被写入单个文件中。谁能建议我如何将代码保存在单独的文件中,希望可以使我建立多个单独的连接?

注意:我不保存数据库。谢谢。

编辑:如果要使用线程,请确保启用以下选项。 check_same_thread =假

例如

db = sqlite3.connect('file:my_db?mode=memory&cache=shared', check_same_thread=False, uri=True)

1 个答案:

答案 0 :(得分:1)

您打开了一个named, in-memory database connection with shared cache。是的,您可以共享该数据库上的缓存,但前提是您使用完全相同的名称。这意味着您需要使用完整的URI方案!

如果您使用db = sqlite3.connect('file:my_db?mode=memory&cache=shared', uri=True)进行连接,则只要原始连接仍处于打开状态,并且进程中的任何其他连接都可以看到同一张表,并且您不介意该表是“专用”,仅在内存中,不适用于使用其他名称的其他进程或连接。当与数据库的最后一个连接关闭时,表消失了。

因此,您还需要在其他模块中保持连接打开才能正常工作!

例如,如果您将模块更改为使用全局连接对象:

db = None

def create_a_table():
    global db
    if db is None:
        db = sqlite3.connect('file:my_db?mode=memory&cache=shared', uri=True)

    with db:
        cursor = db.cursor()

        cursor.execute('''
            CREATE TABLE my_table(id INTEGER PRIMARY KEY, some_data TEXT)
        ''')

然后使用该模块,该表在那里:

>>> import test_create
>>> test_create.create_a_table()
>>> import sqlite3
>>> db = sqlite3.connect('file:my_db?mode=memory&cache=shared', uri=True)
>>> with db:
...     cursor = db.cursor()
...     cursor.execute('''INSERT INTO my_table(some_data) VALUES(?)''', ("a bit of data",))
...
<sqlite3.Cursor object at 0x100d36650>
>>> list(db.cursor().execute('select * from my_table'))
[(1, 'a bit of data')]

另一种实现此目的的方法是在调用函数之前在主代码中打开数据库连接;创建与内存数据库的第一个连接,打开和关闭其他连接不会导致更改丢失。

从文档中:

  

以这种方式命名内存数据库时,它将仅与使用完全相同名称的另一个连接共享其缓存。

如果您不希望数据库仅位于内存中,并且希望将表提交到磁盘(下次打开连接时将其存在),请删除mode=memory组件。