It appears that SQLite has supported multithreaded access since 3.7.13, and Python's sqlite3 module has supported it since 3.4. To use it, you might write code like this:
import sqlite3
dburi = "file:TESTING_MEMORY_DB?mode=memory&cache=shared"
connection = sqlite3.connect(dburi, uri=True, check_same_thread=False)
with connection:
cursor = conneciton.cursor()
cursor.execute("SQL")
This works, but the first thing you'll discover is that you need to lock access to the database or else another thread could corrupt your data. That might look like this:
import threading
import sqlite3
dburi = "file:TESTING_MEMORY_DB?mode=memory&cache=shared"
connection = sqlite3.connect(dburi, uri=True, check_same_thread=False)
# NOTE: You'll need to share this same lock object with every other thread using the database
lock = threading.Lock()
with lock:
with connection:
cursor = connection.cursor()
cursor.execute("SQL")
connection.commit()
Now, if one thread acquires the lock, another thread cannot acquire it until the first thread closes it, and so long as all threads use the same lock object and remember to with lock: before they with connection:, your data will not be corrupted.
However, now I need a way to pass the lock around with the connection. You could do this with separate arguments, or perhaps with a custom class:
import threading
import sqlite3
class LockableSqliteConnection(object):
def __init__(self, dburi):
self.lock = threading.Lock()
self.connection = sqlite3.connect(dburi, uri=True, check_same_thread=False)
dburi = "file:TESTING_MEMORY_DB?mode=memory&cache=shared"
lsc = LockableSqliteConnection(dburi)
with lsc.lock:
with lsc.connection:
cursor = lsc.connection.cursor()
cursor.execute("SQL")
lsc.connection.commit()
This is pretty good, since the name of the class reminds me of what I have, so at least I'm not likely to forget the lock and corrupt my data. But is there a way to do away with the two with statements? Ideally I'd like to combine them into a single with, since I shouldn't ever use the connection without the lock anyway.