Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python sqlalchemy和SQLite共享缓存_Python_Sqlite_Sqlalchemy - Fatal编程技术网

Python sqlalchemy和SQLite共享缓存

Python sqlalchemy和SQLite共享缓存,python,sqlite,sqlalchemy,Python,Sqlite,Sqlalchemy,SQLite支持使用特殊URI打开:内存:数据库时的“共享缓存”(根据): [T] 同一内存数据库可以由两个或多个数据库打开 连接如下: rc=sqlite3\u open(“文件::内存:?缓存=共享”,&db) 通过使用forsqlite3.connect(),我可以在Python 3.4中利用这一点: 然而,我似乎无法让SQLAlchemy实现同样的功能: engine = sqlalchemy.create_engine('sqlite:///:memory:?cache=shared'

SQLite支持使用特殊URI打开
:内存:
数据库时的“共享缓存”(根据):

[T] 同一内存数据库可以由两个或多个数据库打开 连接如下:

rc=sqlite3\u open(“文件::内存:?缓存=共享”,&db)

通过使用for
sqlite3.connect()
,我可以在Python 3.4中利用这一点:

然而,我似乎无法让SQLAlchemy实现同样的功能:

engine = sqlalchemy.create_engine('sqlite:///:memory:?cache=shared')
engine.connect()
...
TypeError: 'cache' is an invalid keyword argument for this function
有没有办法让SQLAlchemy利用共享缓存

编辑
在Python 3.4上,我可以使用
creator
参数
create\u engine
来解决这个问题,但在其他Python版本上仍然存在这个问题:

creator = lambda: sqlite3.connect('file::memory:?cache=shared', uri=True)
engine = sqlalchemy.create_engine('sqlite://', creator=creator)
engine.connect()

您应该避免在较旧的Python版本上传递
uri=True
,问题将得到解决:

import sqlite3
import sys

import sqlalchemy


DB_URI = 'file::memory:?cache=shared'
PY2 = sys.version_info.major == 2
if PY2:
    params = {}
else:
    params = {'uri': True}

creator = lambda: sqlite3.connect(DB_URI, **params)

engine = sqlalchemy.create_engine('sqlite:///:memory:', creator=creator)
engine.connect()

关于SQLite方言的SQLAlchemy文档详细描述了问题和解决方案:

线程/池行为

Pysqlite的默认行为是禁止 在多个线程中使用单个连接。这是 最初打算使用不支持的SQLite的旧版本 支持各种情况下的多线程操作。在里面 特别是,较旧的SQLite版本不允许:memory:数据库 在任何情况下都可以在多个线程中使用

Pysqlite确实包含一个现在未记录的标志,称为
check\u same\u thread
将禁用此检查,但请注意 pysqlite连接在中并发使用仍然不安全 多线程。特别是,任何语句执行调用都会 需要进行外部静音,因为Pysqlite不提供 错误消息的线程安全传播。那么一会儿 甚至
:内存:
数据库可以在现代SQLite中的线程之间共享, Pysqlite没有提供足够的线程安全性,因此不值得使用它 它

SQLAlchemy设置池以使用Pysqlite的默认行为:

  • 当指定
    :memory:
    SQLite数据库时,默认情况下方言为 将使用
    SingletonThreadPool
    。此池维护单个连接 每个线程,以便在当前线程内对引擎的所有访问 使用相同的
    :内存:
    数据库-其他线程将访问 不同的
    :内存:
    数据库

  • 指定基于文件的数据库时,方言将使用
    NullPool
    作为连接的来源。此池关闭并丢弃 立即返回到池的连接。数据库 基于文件的连接具有极低的开销,因此不需要池 必要的。该方案还防止再次使用连接 在不同的线程中,使用SQLite的粗粒度文件效果最好 锁定

在多线程中使用内存数据库

要使用
:内存:
数据库 在多线程场景中,必须共享相同的连接对象 在线程之间,因为数据库只存在于该线程的范围内 连接。
StaticPool
实现将维护一个 全局连接,并且可以将
check\u same\u thread
标志传递给 Pysqlite为
False

from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
              connect_args={'check_same_thread':False},
              poolclass=StaticPool)
请注意,在多线程中使用
:memory:
数据库需要最新版本的SQLite


来源:

如果不将新的sqlite3模块功能向后移植到早期版本,我认为你无法做到这一点。亲爱的上帝,每个线程(不是进程)都有自己的独立数据库(不能与另一个线程的数据库通信)这一事实是微妙的。这篇文章节省了我几天的精力。
from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
              connect_args={'check_same_thread':False},
              poolclass=StaticPool)