多处理应用程序中使用的部分函数的属性错误

Attribute Error in Partial function used in multiprocessing application

我正在尝试对可迭代对象的可迭代对象使用 multiprocessing.map。我使用 partial 是因为我有其他参数需要输入,但是我得到一个属性错误,原始的部分函数没有被识别。

import multiprocessing as mp
from functools import partial

def g(y, x ):
    return x[0] + x[1] + y

z = partial(g, y=1)

pool = mp.Pool(2)
print(pool.map(z, [(1, 2,), (2, 3, ), (3, 4,)]))

我想知道为什么会这样,我做错了什么,我试过翻转论点位置等等。谢谢!

查看 partial documentation如果向调用提供更多参数,它们将附加到 args。它很微妙,但这意味着您不能使用 partial 按名称设置前导参数,然后使用位置参数。删除多处理,您的问题可以重现

>>> import multiprocessing as mp
>>> from functools import partial
>>> 
>>> def g(y, x ):
...     return x[0] + x[1] + y
... 
>>> z = partial(g, y=1)
>>> 
>>> z((1,2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: g() got multiple values for argument 'y'

部分有args=(,)kwargs={"y":1}。调用时,位置参数附加到 args。实际上,调用是

>>> g((1,2), y=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: g() got multiple values for argument 'y'

您希望的参数 x 成为第一个位置参数 y 并且您还尝试定义为 y=1。在这种情况下,您可以通过设置位置参数而不是关键字参数来解决问题。

>>> z = partial(g, 1)
>>> z((1,2))
4

之所以可行,是因为 args=(1,),这是您要设置的 y。在每次调用时附加位置参数,变为 x。但它只起作用,因为你正在替换第一个位置参数。它在设置了一些位置参数而另一些没有设置的更一般情况下不起作用。

回到原来的多处理脚本,解决方案仍然有效。 z 只是 functools.partial class 的一个实例,其 __call__ 方法使用实例的 argskeywordsfunc 属性来打电话。 (添加了设置多处理类型的代码,以便可以在 linux 上测试 windows spawn)

import multiprocessing as mp
from functools import partial
import sys

def g(y, x ):
    return x[0] + x[1] + y

z = partial(g, 1)

if __name__ == "__main__":
    if len(sys.argv) > 1:
        # optional start method for, spawn, forkserver
        mp.set_start_method(sys.argv[1])
    pool = mp.Pool(2)
    print(pool.map(z, [(1, 2,), (2, 3, ), (3, 4,)]))

输出

[4, 6, 8]