SQLite 读取多处理,不启动 imap

SQLite reads with multiprocessing, not starting the 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

当我 运行 使用 "serial" 版本(使用 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 检索结果,这将抑制其中发生的任何错误.