关于python:passing kwargs with multiprocessing.pool.map

passing kwargs with multiprocessing.pool.map

我想用pool.map()将关键字参数传递给我的worker函数。在搜索论坛时,我找不到一个明确的例子。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import multiprocessing as mp

def worker((x,y), **kwargs):
    kwarg_test = kwargs.get('kwarg_test', False)
    print("kwarg_test = {}".format(kwarg_test))    
    if kwarg_test:
        print("Success")
    return x*y

def wrapper_process(**kwargs):
    jobs = []
    pool=mp.Pool(4)
    for i, n in enumerate(range(4)):
        jobs.append((n,i))
    pool.map(worker, jobs) #works
    pool.map(worker, jobs, kwargs) #how to do this?  

def main(**kwargs):
    worker((1,2),kwarg_test=True) #accepts kwargs
    wrapper_process(kwarg_test=True)

if __name__ =="__main__":    
    main()

输出:

1
2
3
4
5
6
7
kwarg_test = True
Success
kwarg_test = False
kwarg_test = False
kwarg_test = False
kwarg_test = False
TypeError: unsupported operand type(s) for //: 'int' and 'dict'

类型错误与在multiprocessing.pool或queue中解析参数有关,我还尝试了其他几种语法,例如列出Kwargs;[Kwargs、Kwargs、Kwargs、Kwargs],以及多次尝试将Kwarg包括在作业列表中,但没有运气。我跟踪multiprocessing.pool中的代码,从map到map异步,一直到task_batches = Pool._get_tasks(func, iterable, chunksize)在pool.py中,我遇到了生成器结构。我很高兴在将来了解更多有关这方面的信息,但现在我只想知道:

是否有一个简单的语法允许通过pool.map传递Kwarg?


如果要迭代其他参数,请使用@arctrusb的答案。

如果您只想传递它们,每个迭代都有相同的值,那么您可以这样做:

1
2
from functools import partial
pool.map(partial(worker, **kwargs), jobs)

部分"binds"参数到函数。但是,旧版本的python无法序列化部分对象。


multiprocessing.pool.Pool.map文件规定:

A parallel equivalent of the map() built-in function (it supports only one iterable argument though). It blocks until the result is ready.

我们只能传递一个无可辩驳的论点。故事的结尾。但我们可以幸运地想到一个解决方法:定义一个接受单个参数的worker_wrapper函数,将其解包为args和kwargs,并将它们传递给worker

1
2
3
def worker_wrapper(arg):
    args, kwargs = arg
    return worker(*args, **kwargs)

在你的wrapper_process中,你需要从jobs(甚至在构建作业时直接调用)并调用worker_wrapper

1
2
arg = [(j, kwargs) for j in jobs]
pool.map(worker_wrapper, arg)

这是一个正在运行的实现,尽可能靠近原始的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import multiprocessing as mp

def worker_wrapper(arg):
    args, kwargs = arg
    return worker(*args, **kwargs)

def worker(x, y, **kwargs):
    kwarg_test = kwargs.get('kwarg_test', False)
    # print("kwarg_test = {}".format(kwarg_test))    
    if kwarg_test:
        print("Success")
    else:
        print("Fail")
    return x*y

def wrapper_process(**kwargs):
    jobs = []
    pool=mp.Pool(4)
    for i, n in enumerate(range(4)):
        jobs.append((n,i))
    arg = [(j, kwargs) for j in jobs]
    pool.map(worker_wrapper, arg)

def main(**kwargs):
    print("=> calling `worker`")
    worker(1, 2,kwarg_test=True) #accepts kwargs
    print("=> no kwargs")
    wrapper_process() # no kwargs
    print("=> with `kwar_test=True`")
    wrapper_process(kwarg_test=True)

if __name__ =="__main__":    
    main()

通过测试:

1
2
3
4
5
6
7
8
9
10
11
12
=> calling `worker`
Success
=> no kwargs
Fail
Fail
Fail
Fail
=> with `kwar_test=True`
Success
Success
Success
Success