我已经尝试了我能想到的一切,但我无法弄清楚为什么以下多处理代码不会启动循环:
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
当我使用“serial”版本(使用itertools.imap
)运行它时,我得到(0,) (1,) (2,) (3,) (4,)
的预期输出。使用multiprocessing.imap
版本,我什么也得不到,循环静默退出。我显然与sqlite游标有关,切换到cursor=range(5)
有效。
为什么多处理不在这里工作?
答案 0 :(得分:2)
默认情况下,sqlite3
不允许您访问实际创建它的hte线程之外的任何对象。 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
检索结果,这会抑制任何错误发生在它里面。