SQLite 使用多处理读取,而不是启动 imap



我已经尝试了我能想到的一切,但我无法弄清楚为什么以下多处理代码不会启动循环:

import sqlite3, itertools
# Dummy table
conn = sqlite3.connect(":memory:")
conn.execute('CREATE TABLE numbers (num integer)')
conn.executemany("INSERT INTO numbers VALUES (?)",
                 ((x,) for x in range(5)))
conn.commit()
cmd_search = "SELECT * FROM numbers"
cursor = conn.execute(cmd_search)
def nothing(x): return x
import multiprocessing
P = multiprocessing.Pool()
#ITR  = P.imap(nothing,cursor)           # parallel version
ITR  = itertools.imap(nothing, cursor)   # serial   version
for x in ITR: print x

当我使用"串行"版本(使用 itertools.imap)运行时,我得到了 (0,) (1,) (2,) (3,) (4,) 的预期输出。使用 multiprocessing.imap 版本,我什么也得不到,循环静默退出。我显然与 sqlite 光标有关,切换到cursor=range(5)工作。

为什么多处理在这里不起作用?

默认情况下,sqlite3 不允许你在实际创建它的线程之外访问它的任何对象。 multiprocessing.Pool使用后台线程对对象进行排队,这违反了此规则。您可以通过将check_same_thread=False传递给sqlite3.connect来禁用该检查:

conn = sqlite3.connect(":memory:", check_same_thread=False)

一旦我进行了该更改,您的代码就可以正常运行。如果没有该更改,我会看到此错误:

ProgrammingError: SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 140082824808256 and this is thread id 140082770409216

我不确定为什么你没有看到任何错误消息; 我没有得到的唯一方法是我删除了for x in ITR: print x行,因为没有它,您实际上不会尝试从Pool中检索结果,这将抑制其中发生的任何错误。

最新更新