我正在尝试编写一个函数,该函数将附加到python中自身之外的列表中。用for循环测试,没有问题。然而,当我试图让它以多处理方式运行时,它就不再工作了。我创建了一个简单得多的代码来演示故障排除的问题:
from multiprocessing import Pool
items = []
def myFunc(a,b):
data = (a,b)
items.append(data)
if __name__ == '__main__':
with Pool(2) as p:
p.starmap(myFunc,[(0,1),(2,3)])
print(items)
应该带着回来
[(0,1),(2,3)]
与for循环一样,列表是空的,有指针吗?
一种方法是使用由SyncManager
实例获得的list
,该实例通过调用multiprocessing.Manager()
并将其作为参数传递给myfunc
:而获得
from multiprocessing import Pool, Manager
import functools
def myFunc(items, a, b):
data = (a,b)
items.append(data)
if __name__ == '__main__':
manager = Manager()
items = manager.list()
with Pool(2) as p:
p.starmap(functools.partial(myFunc, items),[(0,1),(2,3)])
print(items)
打印:
[(2, 3), (0, 1)]
另一种更接近您所拥有的方法是,使用这个特殊的可共享进程间list
初始化池中的每个进程,而不必将其作为参数传递给您的工作人员:
from multiprocessing import Pool, Manager
def init_processes(l):
global items
items = l
def myFunc(a, b):
data = (a,b)
items.append(data)
if __name__ == '__main__':
manager = Manager()
items = manager.list()
with Pool(2, initializer=init_processes, initargs=(items,)) as p:
p.starmap(myFunc, [(0,1),(2,3)])
print(items)
打印:
[(0, 1), (2, 3)]
因此,每个作业提交一次(即,对starmap
的调用中的每个参数传递一次(,而对池中的每个进程传递一次列表,就成了一个问题在你的情况下,我认为在成本方面几乎是一样的,但通常第二种方法会更好。
您会注意到,根据哪个调用首先完成,元组的添加顺序是不确定的。然而,调用的返回值将严格按照调用的顺序排列:
from multiprocessing import Pool, Manager
import functools
def myFunc(items, a, b):
data = (a,b)
items.append(data)
return data # let's also return the tuple
if __name__ == '__main__':
manager = Manager()
items = manager.list()
with Pool(2) as p:
results = list(p.starmap(functools.partial(myFunc, items),[(0,1),(2,3)]))
print(items)
print(results)
打印:
[(2, 3), (0, 1)]
[(0, 1), (2, 3)]
我不得不运行以上几次,以使得到的items
数组为[(2, 3), (0, 1)]
而不是[(0, 1), (2, 3)]
,但您仍然可以看到,从对myFunc
的调用返回的值对应于";乔布斯;已提交。
您可以在数据被处理后返回数据,然后将其添加到项目列表中。
from multiprocessing import Pool
items = []
def myFunc(a,b):
data = (a,b)
# manipulate data...
return data
if __name__ == '__main__':
with Pool(2) as p:
items += p.starmap(myFunc,[(0,1),(2,3)])
print(items)
输出:
[(0, 1), (2, 3)]
多处理意味着代码在另一个进程中运行。甚至在另一个Python运行库中也是如此。
调用机制串行化您的列表,并以无缝的方式在另一个进程中对其进行反串行化,但它在另一端是一个200%独立和独立的对象(100%表示不在同一列表中,+100%表示在另一进程中:-(
该语言提供的更接近列表的是multiprocessing.Queue
类,这是一个类似序列的对象,以透明的方式操作进程间通信部分
虽然您可以使用concurrent.futures轻松地从进程外工作者函数中获取返回值,这可能会导致更容易理解的代码库,但这将与您认为使用";列表";。(尽管我推荐它(