将列表的列表传递给multiprocessing.Pool似乎不起作用

0 投票
1 回答
4036 浏览
提问于 2025-04-18 07:15
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会是空的,这正是你想要的结果。

撰写回答