如何将仅关键字参数应用于多处理池中的函数?

Posted

技术标签:

【中文标题】如何将仅关键字参数应用于多处理池中的函数?【英文标题】:How to apply keyword-only arguments to a function in a multiprocessing pool? 【发布时间】:2020-02-15 14:50:32 【问题描述】:

我有一个只接受关键字参数的函数,并希望在进程池中运行它。如何将我的条目从可迭代项作为关键字参数传递给进程中的函数?

import multiprocessing

greetees = ('Foo', 'Bar')

def greet(*, greetee):
    return f'Hello, greetee!'

我尝试使用 multiprocessing.map:

greetings = multiprocessing.Pool(2).map(greet, greetees)
for greeting in greetings:
    print(greeting)

但这引发了一个异常,正如预期的那样:

multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 44, in mapstar
    return list(map(*args))
TypeError: greet() takes 0 positional arguments but 1 was given
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/bengt/Projekte/gitlab.com/PFASDR/PFASDR.Code.Main/pfasdr/neural/multi_pool_kwargs.py", line 10, in <module>
    greetings = multiprocessing.Pool(2).map(greet, greetees)
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 266, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 644, in get
    raise self._value
TypeError: greet() takes 0 positional arguments but 1 was given

如果我删除星号以不要求参数仅是关键字,则效果很好:

[...]
def greet(greetee):
    return f'Hello, greetee!'
[...]

输出:

Hello, Foo!
Hello, Bar!

【问题讨论】:

【参考方案1】:

感谢Mad Physicist 和this QnA,可以使用functools.partial 将仅关键字参数注入函数:

from functools import partial
greetings = []
for i in range(len(greetees)):
    kwargs = 'greetee': greetees[i]
    greet_partial = partial(greet, **kwargs)
    greetings.append(multiprocessing.Pool(2).apply(greet_partial))

或具有较少可变出血:

from functools import partial
greetings = [
    multiprocessing.Pool(2).apply(
        partial(greet, **'greetee': greetees[i])
    )
    for i in range(len(greetees))
]

【讨论】:

【参考方案2】:

这里的一个解决方案是使用Pool.apply or Pool.apply_async:

greetings = list(
    multiprocessing.Pool(2).apply(greet, kwds='greetee': greetees[i])
    for i in range(len(greetees))
)
for greeting in greetings:
    print(greeting)

输出:

Hello, Foo!
Hello, Bar!

【讨论】:

这应该是公认的答案还是有更好的方法? 谢谢,我确实看到了这个答案,但不明白它与同样的问题有关。是的,这确实有效。我将发布另一个答案。 您应该在另一个问题中发帖。你同意你的本质上是重复的吗? 不,我不认为这些是重复的。他们尝试使用functools.partial 将3 个静态关键字参数(bcd)和一个(a)作为位置参数使用Pool.map 传递给函数。我不能做后者,因为我的函数的参数是关键字。因此,我只能使用 applyapply_async 传递仅关键字参数。

以上是关于如何将仅关键字参数应用于多处理池中的函数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flask-RESTless 中使用关键字参数

创建函数-----------(在函数中使用变量向函数传递参数在函数中处理变量关键字local)

如何将关键字参数添加到 Python 2.7 中的包装函数?

如何将关键字对作为参数传递给函数中的模块?

python如何将可选参数或关键字参数从一个函数传递到另一个函数?

如何将字典传递给带有关键字参数的函数?