SQLite улучшился за последние 4 года, поэтому теперь доступны общие базы данных в памяти. Проверьте следующий код:
import sqlite3
foobar_uri = 'file:foobar_database?mode=memory&cache=shared'
not_really_foobar_uri = 'file:not_really_foobar?mode=memory&cache=shared'
# connect to databases in no particular order
db2 = sqlite3.connect(foobar_uri, uri=True)
db_lol = sqlite3.connect(not_really_foobar_uri, uri=True)
db1 = sqlite3.connect(foobar_uri, uri=True)
# create cursor as db2
cur2 = db2.cursor()
# create table as db2
db2.execute('CREATE TABLE foo (NUMBER bar)')
# insert values as db1
db1.execute('INSERT INTO foo VALUES (42)')
db1.commit()
# and fetch them from db2 through cur2
cur2.execute('SELECT * FROM foo')
print(cur2.fetchone()[0]) # 42
# test that db_lol is not shared with db1 and db2
try:
db_lol.cursor().execute('SELECT * FROM foo')
except sqlite3.OperationalError as exc:
print(exc) # just as expected
базы данных доступы запутанный умышленно, чтобы показать, что два соединения с базой данных в оперативной памяти, с тем же именем, то же самое с точки SQLite зрения.
Ссылки:
- SQLite URIs
- SQLite shared cache
К сожалению, подключение по URI доступен только с Python 3.4. Однако, если у вас есть Python 2.6 или новее (но не Python 3), встроенный модуль sqlite3
по-прежнему способен импортировать соединения APSW, которые могут быть использованы для достижения такого же эффекта. Здесь идет опускание модуля sqlite3
:
from sqlite3 import *
from sqlite3 import connect as _connect
from apsw import Connection as _ApswConnection
from apsw import SQLITE_OPEN_READWRITE as _SQLITE_OPEN_READWRITE
from apsw import SQLITE_OPEN_CREATE as _SQLITE_OPEN_CREATE
from apsw import SQLITE_OPEN_URI as _SQLITE_OPEN_URI
# APSW and pysqlite use different instances of sqlite3 library, so initializing
# APSW won't help pysqlite. Because pysqlite does not expose any way to
# explicitly call sqlite3_initialize(), here goes an ugly hack. This only has
# to be done once per process.
_connect(':memory:').close()
def connect(database, timeout=5.0, detect_types=0, isolation_level=None,
check_same_thread=True, factory=Connection, cached_statements=100,
uri=False):
flags = _SQLITE_OPEN_READWRITE | _SQLITE_OPEN_CREATE
if uri:
flags |= _SQLITE_OPEN_URI
db = _ApswConnection(database, flags, None, cached_statements)
conn = _connect(db, timeout, detect_types, isolation_level,
check_same_thread, factory, cached_statements)
return conn
Опишите ситуацию, в которой это необходимо. Могут ли быть другие варианты, а не использовать sqlite из нескольких потоков? –
@Muhammad Alkarouri Мне нужно было это для модульного тестирования многопоточного приложения базы данных. Если файл используется (как и в реальном приложении), я могу открыть несколько подключений, если просто отлично. Я закончил обертывание логики базы данных одним потоком, который использует шаблон потребителя и возвращает отложенные данные, которые он заполняет, когда он попадает на запрос. – aaronasterling