2

我有一个列表理解:

thingie=[f(a,x,c) for x in some_list]

我将其并行化如下:

from multiprocessing import Pool

pool=Pool(processes=4)

thingie=pool.map(lambda x: f(a,x,c), some_list)

但我收到以下错误:

_pickle.PicklingError: Can't pickle <function <lambda> at 0x7f60b3b0e9d8>:
attribute lookup <lambda> on __main__ failed

我试图安装pathos显然解决了这个问题的包,但是当我尝试导入它时,我得到了错误:

ImportError: No module named 'pathos'
4

2 回答 2

5

好的,所以这个答案仅供记录,我已经在评论对话期间与问题的作者一起弄清楚了。

multiprocessing需要在进程之间传输每个对象,因此它用于pickle在一个进程中序列化它并在另一个进程中反序列化。这一切都很好,但pickle不能序列化lambda。AFAIR 之所以如此,是因为pickle需要函数源来序列化它,并且lambda不会拥有它,但我不是 100% 确定并且不能引用我的源。

如果您在 1 个参数函数上使用它不会有任何问题map()- 您可以传递该函数而不是lambda. 如果您有更多参数,例如在您的示例中,则需要使用def关键字定义一些包装器:

from multiprocessing import Pool

def f(x, y, z):
    print(x, y, z)

def f_wrapper(y):
    return f(1, y, "a")

pool = Pool(processes=4)

result = pool.map(f_wrapper, [7, 9, 11])
于 2015-05-21T14:11:01.747 回答
4

就在我关闭它之前,我找到了另一种使用 Python 3 执行此操作的方法,使用 functools,

假设我有一个f包含三个变量的函数f(a,x,c),其中一个我想可能,比如说x。我可以使用以下代码基本上完成@FilipMalczak 的建议:

import functools
from multiprocessing import Pool


f1=functools.partial(f,a=10)

f2=functools.partial(f2,c=10)

pool=Pool(processes=4)
final_answer=pool.map(f2,some_list)
于 2015-05-22T08:51:09.010 回答