我已经尝试了我能想到的一切,但我无法弄清楚为什么以下多处理代码不会启动循环:
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
中检索结果,这将抑制其中发生的任何错误。