带有map_async的python多处理池

时间:2013-05-14 11:42:32

标签: python multiprocessing

我尝试在python中使用带有Pool的多处理包。

我有map_async函数调用的函数f:

from multiprocessing import Pool

def f(host, x):
    print host
    print x

hosts = ['1.1.1.1', '2.2.2.2']
pool = Pool(processes=5)
pool.map_async(f,hosts,"test")
pool.close()
pool.join()

此代码有下一个错误:

Traceback (most recent call last):
  File "pool-test.py", line 9, in <module>
    pool.map_async(f,hosts,"test")
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 290, in map_async
    result = MapResult(self._cache, chunksize, len(iterable), callback)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 557, in __init__
    self._number_left = length//chunksize + bool(length % chunksize)
TypeError: unsupported operand type(s) for //: 'int' and 'str'

我不知道如何将超过1个参数传递给f函数。有什么办法吗?

3 个答案:

答案 0 :(得分:9)

"test"被解释为map_async的{​​{1}}关键字参数(请参阅the docs)。

你的代码应该是(这里从我的IPython会话中复制粘贴):

chunksize

注意:在Python 3中,您可以使用from multiprocessing import Pool def f(arg): host, x = arg print host print x hosts = ['1.1.1.1', '2.2.2.2'] args = ((host, "test") for host in hosts) pool = Pool(processes=5) pool.map_async(f, args) pool.close() pool.join() ## -- End pasted text -- 1.1.1.1 test 2.2.2.2 test ,它将从元组中解压缩参数。您将能够避免明确地执行starmap

答案 1 :(得分:6)

Pool在Python 3中返回一个上下文管理器,因此可以使用with语句。这避免了异常问题,并且意味着无需关闭和加入。在这种情况下,函数总是接收x变量的常量,因此可以通过部分求值来处理。 map_async很懒,所以我们需要得到动作的结果,也可以只使用map。因此:

from multiprocessing import Pool
from functools import partial

def f(host, x):
    print(host)
    print(x)

hosts = ('1.1.1.1', '2.2.2.2')
with Pool(processes=5) as pool:
    pool.map(partial(f, x='test'), hosts)

结果:

1.1.1.1
test
2.2.2.2
test

答案 2 :(得分:1)

我记得,

,Pool()。map()和.map_async()只接受一个参数。这个限制可以通过传递一个列表来解决,但当然你需要一个自定义函数来设计一个列表(如)对象作为参数。

一种方法是编写自定义代码一次 - 也就是一般的“函数+ args”包装器。我做了类似的事情(注意:这只是部分测试):

def tmp_test():
    # a short test script:
    #
    A=[[1,2], [2,3], [4,5], [6,7]]
    P=mpp.Pool(mpp.cpu_count())
    X=P.map_async(map_helper, [[operator.eq]+a for a in A])
    #
    return X.get()


def null_funct(args=[], kwargs={}):
    # a place-holder 
    pass
#
def map_helper(args_in = [null_funct, [], {}]):
    # helper function for pool.map_async(). pass data as a list(-like object):
    # [function, [args], {kwargs}] (though we'll allow for some mistakes).
    #
    funct = args_in[0]
    #
    # allow for different formatting options:
    if not (isinstance(args_in[1], list) or isinstance(args_in[1], tuple) or isinstance(args_in[1], dict)):
        # probably passed a list of parameters. just use them:
        args = args_in[1:]
        #
        return funct(*args)
    #
    # if the args are "properly" formatted:
    args=[]
    kwargs = {}
    for arg in args_in[1:]:
        # assign list types to args, dict types to kwargs...
        if isinstance(arg, list) or isinstance(arg, tuple): args += arg
        if isinstance(arg, dict): kwargs.update(arg)
    return funct(*args, **kwargs)