将列表的列表传递给multiprocessing.Pool似乎不起作用
from multiprocessing import Pool
data_table = None
def init_data_table(my_data_table = [], *args):
global data_table
data_table = my_data_table
def process_data(index):
# create data processor object and run cpu intensive task here
return str(index) + " " + data_table[index][0]
def main():
# call db functions once and get data table from db
data_table = ...
pool = Pool(processes = 4, initializer=init_data_table, initargs=(data_table))
x = pool.map(process_data, range(10))
问题是,当我尝试传递 data_table
并在后面访问它时,它不工作。我收到了这个错误:
IndexError: list index out of range
我不确定这样传递一个复杂的数据结构,比如元组或列表的列表,给 Pool()
函数是否正确,这样它才能被分叉的子进程访问。实际上,这是我想要一次性获取的共享数据,因为从数据库调用它的成本很高,我希望让这些进程可以访问它。
任何帮助都将非常感谢,谢谢。
1 个回答
3
multiprocessing.Pool
的文档中提到关于initializer
的内容如下:
如果
initializer
不是None,那么每个工作进程在启动时都会调用initializer(*initargs)
。
所以在你的情况下,它会调用init_data_table(*data_table)
。因为有个*
,它会尝试把你的列表中的每个子列表拆开,分别赋值给init_data_table
定义中的变量。你是这样定义的:
def init_data_table(my_data_table=[], *args):
所以,当Python尝试拆分这个列表时,第一个子列表会被放到my_data_table
里,而其他的子列表会被放到一个元组中,赋值给*args
。为了避免这种情况,你需要在把data_table
赋值给initargs
时,把它放进一个元组里。看起来你是想这么做的,但你忘了加上结尾的逗号:
pool = Pool(processes = 4, initializer=init_data_table, initargs=(data_table,))
这样,Python最终会调用init_data_table(*(data_table,))
,这会把整个data_table
列表都放进my_data_table
里,而*args
会是空的,这正是你想要的结果。