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

时间:2015-04-25 03:10:44

标签: python sqlite python-multiprocessing

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

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)有效。

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

1 个答案:

答案 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检索结果,这会抑制任何错误发生在它里面。