我尝试在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函数。有什么办法吗?
答案 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)