Python多处理-将结果写入同一文件

Beh*_*ali 2 python sqlite multiprocessing

我有一个简单的函数,将一些计算的输出写入sqlite表中。我想在Python中通过多处理并行使用此函数。我的具体问题是,当每个进程尝试将其结果写入同一张表时,如何避免冲突?运行代码给我这个错误:sqlite3.OperationalError:数据库被锁定。

import sqlite3
from multiprocessing import Pool

conn = sqlite3.connect('test.db')
c = conn.cursor()
c.execute("CREATE TABLE table_1 (id int,output int)")

def write_to_file(a_tuple):
    index = a_tuple[0]
    input = a_tuple[1]
    output = input + 1
    c.execute('INSERT INTO table_1 (id, output)' 'VALUES (?,?)', (index,output))

if __name__ == "__main__":
    p = Pool()
    results = p.map(write_to_file, [(1,10),(2,11),(3,13),(4,14)])
    p.close()
    p.join()

Traceback (most recent call last):
sqlite3.OperationalError: database is locked
Run Code Online (Sandbox Code Playgroud)

Rol*_*ith 5

用一个 Pool是个好主意。

我看到了三种可能的解决方案。

首先,不要让池工作程序尝试将数据插入数据库,而是让工作程序将数据返回给父进程。

在父进程中,使用imap_unordered代替map。这是一个迭代过程,一旦可用就开始提供值。然后,父级可以将数据插入数据库。

这将序列化对数据库的访问,从而避免了该问题。

如果要插入到数据库中的数据相对较小,但是更新经常发生,则首选此解决方案。因此,与计算数据相比,更新数据库需要花费相同或更多的时间。


其次,您可以使用Lock。然后,工人应该

  • 获取锁,
  • 打开数据库,
  • 插入值,
  • 关闭数据库,
  • 释放锁。

这将避免将数据发送到父进程的开销。但是,相反,您可能会让工作人员停滞不前,等待将其数据写入数据库。

如果要插入的数据量很大,但是计算数据比将数据插入数据库要花费更长的时间,则这将是首选解决方案。


第三,您可以让每个工作人员写入其自己的数据库,然后将它们合并。您可以直接在sqlite甚至Python中执行此操作。尽管有大量数据,但我不确定后者是否有优势。