Serialización de Sqlite3 en Python

Para utilizar completamente la concurrencia, SQLite3 permite que los subprocesos accedan a la misma conexión de tres maneras:

  1. De un solo hilo En este modo, todos los mutexes están desactivados y SQLite no es seguro para usar en más de un solo hilo a la vez.
  2. Multihilo. En este modo, SQLite puede ser utilizado de forma segura por varios subprocesos siempre que no se use una sola conexión de base de datos simultáneamente en dos o más subprocesos.
  3. Serializado En modo serializado, SQLite puede ser utilizado de manera segura por múltiples hilos sin restricciones.

¿Alguien sabe cómo puedo hacer la conexión serializada en Python?
Python tiene “check_same_thread” que permite cambiar entre subprocesos múltiples y subprocesos únicos; Sin embargo, no puedo descubrir cómo debo hacer que sea serializado.

El módulo SQLite de Python no es seguro para subprocesos. Si deshabilita su comprobación, debe asegurarse de que todo el código esté en serie y eso incluye la recolección de basura. (Mi módulo APSW es ​​seguro para subprocesos y también maneja correctamente los problemas de seguridad del subproceso del mensaje de error).

Sin embargo, es seguro usar múltiples conexiones independientes al mismo tiempo en el mismo proceso y le recomendaría que lo haga. Además, cambie la base de datos al modo de registro de escritura anticipada y obtendrá un muy buen rendimiento incluso con mucha escritura.

Escribí una biblioteca para resolver esto. Funciona para mi.

https://github.com/palantir/sqlite3worker

La página de sqlite http://www.sqlite.org/threadsafe.html dice: “El modo predeterminado está serializado”. ¿Lo has probado y has encontrado que esto no es cierto?

Editar:


Si no funciona, ¿tal vez ctypes? No tengo idea si esto tendría algún efecto en el módulo sqlite cargado. Supongo que sospecho que no; como me imagino, la sqlite3_initialize() es probable que se llame cuando se carga el módulo? ¿O tal vez solo cuando creas un objeto de base de datos?

http://www.sqlite.org/c3ref/config.html

 >>> import sqlite3 >>> import ctypes >>> from ctypes.util import find_library >>> sqlite_lib = ctypes.CDLL(find_library('sqlite3')) >>> sqlite_lib.sqlite3_config(3) # http://www.sqlite.org/c3ref/c_abort.html 0 # no error.... >>> 

Desde Verse Quiz , puede interesarle los __init__ , __serve y __fetch para comenzar a crear una interfaz de base de datos SQLite3 serializada en Python. Espero que te ayude más!


 import _thread import sqlite3 import queue ################################################################################ class Server: """Execute a protected SQLite3 database on a singular thread. Since a SQLite3 database can only accept queries on the thread that it was created on, this server receives requests through a queue and sends back the result through a list and mutex mechanism.""" def __init__(self, *args): """Initialize the Server with a SQLite3 database thread.""" self.__lock = _thread.allocate_lock() self.__lock.acquire() _thread.start_new_thread(self.__serve, args) self.__lock.acquire() del self.__lock if self.__error is not None: raise self.__error del self.__error def __serve(self, *args): """Run a server continuously to answer SQL queries. A SQLite3 connection is made in this thread with errors being raised again for the instantiator. If the connection was made successfully, then the server goes into a continuous loop, processing SQL queries.""" try: database = sqlite3.connect(*args) except: self.__error = error = sys.exc_info()[1] else: self.__error = error = None self.__lock.release() if error is None: self.__QU = queue.Queue() while True: lock, one, sql, parameters, ret = self.__QU.get() try: cursor = database.cursor() cursor.execute(sql, parameters) data = cursor.fetchone() if one else cursor.fetchall() ret.extend([True, data]) except: ret.extend([False, sys.exc_info()[1]]) lock.release() def fetch(self, one, sql, *parameters): """Execute the specified SQL query and return the results. This is a powerful shortcut method that is the closest connection other threads will have with the SQL server. The parameters for the query are dumped into a queue, and the answer is retrieved when it becomes available. This prevents SQLite3 from throwing exceptions.""" lock, ret = _thread.allocate_lock(), [] lock.acquire() self.__QU.put((lock, one, sql, parameters, ret)) lock.acquire() if ret[0]: return ret[1] raise ret[1]