本问题已经有最佳答案,请猛点这里访问。
我需要一些方法来使用pool.map()中接受多个参数的函数。根据我的理解,pool.map()的目标函数只能有一个iterable作为参数,但是有没有其他参数也可以传入的方法?在这种情况下,我需要传递一些配置变量,比如锁(),并将信息记录到目标函数中。
我试过做一些研究,我认为我可以使用部分函数使它工作?但是我不完全理解这些是如何工作的。任何帮助都将不胜感激!下面是一个简单的例子,说明我想做什么:
def target(items, lock):
for item in items:
# Do cool stuff
if (... some condition here ...):
lock.acquire()
# Write to stdout or logfile, etc.
lock.release()
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
pool.map(target(PASS PARAMS HERE), iterable)
pool.close()
pool.join()
这里讨论:stackoverflow.com/questions/5442910/…(我成功地使用了J.F.Sebastien的"star"方法)
请在使用多进程时使用try/finally子句,finally中包含close()和join(),以确保在发生错误时关闭进程。stackoverflow.com/questions/30506489/…
您可以使用EDOCX1[0]进行此操作(如您怀疑的那样):
from functools import partial
def target(lock, iterable_item):
for item in iterable_item:
# Do cool stuff
if (... some condition here ...):
lock.acquire()
# Write to stdout or logfile, etc.
lock.release()
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
l = multiprocessing.Lock()
func = partial(target, l)
pool.map(func, iterable)
pool.close()
pool.join()
例子:
def f(a, b, c):
print("{} {} {}".format(a, b, c))
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
a ="hi"
b ="there"
func = partial(f, a, b)
pool.map(func, iterable)
pool.close()
pool.join()
if __name__ =="__main__":
main()
号
输出:
hi there 1
hi there 2
hi there 3
hi there 4
hi there 5
太棒了,我想我所需要的就是一个这样清晰的例子。非常感谢!
很好的例子。但有一个问题:为什么在target的定义中有for item in items:?
@让·弗朗索瓦。复制/粘贴错误!谢谢你指出。
那些对锁有问题的人,请查看stackoverflow.com/questions/25557686/…
如果变量在第一个位置呢?如test(input, p1, p2, p3=None),我有p1, p2, p3固定,input变化?
@Mithril写了一个这样的顶级函数:def mytest(p1, p2, input, p3=None): test(input, p1, p2, p3=None),然后做func = partial(mytest, some_p1, some_p2, p3=some_p3),把func传递给pool.map。
您可以使用允许多个参数的map函数,就像在pathos中找到的multiprocessing的分叉一样。
>>> from pathos.multiprocessing import ProcessingPool as Pool
>>>
>>> def add_and_subtract(x,y):
... return x+y, x-y
...
>>> res = Pool().map(add_and_subtract, range(0,20,2), range(-5,5,1))
>>> res
[(-5, 5), (-2, 6), (1, 7), (4, 8), (7, 9), (10, 10), (13, 11), (16, 12), (19, 13), (22, 14)]
>>> Pool().map(add_and_subtract, *zip(*res))
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)]
pathos使您能够轻松地用多个输入嵌套分层并行映射,因此我们可以扩展我们的示例来证明这一点。
>>> from pathos.multiprocessing import ThreadingPool as TPool
>>>
>>> res = TPool().amap(add_and_subtract, *zip(*Pool().map(add_and_subtract, range(0,20,2), range(-5,5,1))))
>>> res.get()
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)]
。
更有趣的是,构建一个可以传递到池中的嵌套函数。这是可能的,因为pathos使用dill,它可以序列化Python中的几乎所有内容。
>>> def build_fun_things(f, g):
... def do_fun_things(x, y):
... return f(x,y), g(x,y)
... return do_fun_things
...
>>> def add(x,y):
... return x+y
...
>>> def sub(x,y):
... return x-y
...
>>> neato = build_fun_things(add, sub)
>>>
>>> res = TPool().imap(neato, *zip(*Pool().map(neato, range(0,20,2), range(-5,5,1))))
>>> list(res)
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)]
。
但是,如果您不能走出标准库,您将不得不以另一种方式进行。在这种情况下,最好的选择是使用multiprocessing.starmap,如这里所示:python multiprocessing pool.map用于多个参数(由@roberto在OP文章的注释中指出)
获取pathos:https://github.com/uqfoundation
如果您没有访问functools.partial的权限,也可以为此使用包装函数。
def target(lock):
def wrapped_func(items):
for item in items:
# Do cool stuff
if (... some condition here ...):
lock.acquire()
# Write to stdout or logfile, etc.
lock.release()
return wrapped_func
def main():
iterable = [1, 2, 3, 4, 5]
pool = multiprocessing.Pool()
lck = multiprocessing.Lock()
pool.map(target(lck), iterable)
pool.close()
pool.join()
。
这使得target()成为一个接受锁的函数(或任何你想给出的参数),它将返回一个只接受一个iterable作为输入的函数,但仍然可以使用你的所有其他参数。这就是最终传递给pool.map()的内容,然后应该毫无问题地执行。
我已经非常晚了,但这段代码不起作用,因为嵌套函数不能被pickle。调用target(lck)将返回嵌套的wrapped_func函数,该函数需要经过处理才能传递给工作进程,并且总是失败。