SQLite ha mejorado en los últimos 4 años, por lo que ahora son posibles las bases de datos compartidas en memoria. Compruebe el siguiente código:
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
accesos de base de datos se enredan intencionadamente, para mostrar que dos conexiones a la base de datos en memoria con el mismo nombre son equivalentes desde el punto de vista de SQLite.
Referencias:
- SQLite URIs
- SQLite shared cache
Desafortunadamente, conexión por URI sólo está disponible desde Python 3.4. Sin embargo, si tiene Python 2.6 o posterior (pero no Python 3), el módulo sqlite3
incorporado aún puede importar conexiones APSW, que se pueden usar para lograr el mismo efecto. Aquí va la gota en el reemplazo sqlite3
módulo:
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
Puede por favor describir el escenario para el que esto es necesario? ¿Puede haber otras opciones en lugar de usar sqlite desde varios subprocesos? –
@Muhammad Alkarouri Lo necesitaba para probar la unidad de una aplicación de base de datos de múltiples hilos. Si se usa un archivo (como lo sería en la aplicación real), entonces puedo abrir múltiples conexiones si está bien. Terminé envolviendo la lógica de la base de datos en un hilo que usa el patrón del consumidor y devuelve diferidos que llena cuando llega a la solicitud. – aaronasterling