Я работаю над резьбовым приложением, где один поток будет подавать Queue
с объектами, подлежащими изменению, и затем ряд других потоков будет считываться из очереди, вносить изменения и сохранять изменения.Peewee, SQLite и threading
Приложение не нуждается в большом количестве параллелизма, поэтому я хотел бы придерживаться базы данных SQLite. Вот небольшой пример, иллюстрирующий применение:
import queue
import threading
import peewee as pw
db = pw.SqliteDatabase('test.db', threadlocals=True)
class Container(pw.Model):
contents = pw.CharField(default="spam")
class Meta:
database = db
class FeederThread(threading.Thread):
def __init__(self, input_queue):
super().__init__()
self.q = input_queue
def run(self):
containers = Container.select()
for container in containers:
self.q.put(container)
class ReaderThread(threading.Thread):
def __init__(self, input_queue):
super().__init__()
self.q = input_queue
def run(self):
while True:
item = self.q.get()
with db.execution_context() as ctx:
# Get a new connection to the container object:
container = Container.get(id=item.id)
container.contents = "eggs"
container.save()
self.q.task_done()
if __name__ == "__main__":
db.connect()
try:
db.create_tables([Container,])
except pw.OperationalError:
pass
else:
[Container.create() for c in range(42)]
db.close()
q = queue.Queue(maxsize=10)
feeder = FeederThread(q)
feeder.setDaemon(True)
feeder.start()
for i in range(10):
reader = ReaderThread(q)
reader.setDaemon(True)
reader.start()
q.join()
На основе Peewee документы многопоточность должны быть поддержаны для SQLite. Тем не менее, я продолжаю получать печально известную ошибку peewee.OperationalError: database is locked
с выходом ошибки, указывающим на линию container.save()
.
Как мне обойти это?
Спасибо за ваш ответ! Threading по-прежнему немного вуду для меня, поэтому я рад, что это была не очевидная ошибка с моей стороны. Интересно, что употребление инструкции SELECT, по-видимому, является ключевым здесь - я не вижу никакой разницы, используя 'db.execution_context (False)' или 'с db.atomic()'. Фактически, употребляя инструкцию SELECT, мне даже не кажется, что нужно использовать «ExecutionContext()». Итак, я полагаю, что инструкция SELECT фактически блокировала базу данных? – digitaldingo