无法使用multiprocessing.Pool将参数传递给方法

时间:2017-09-15 02:01:09

标签: python python-2.7 multiprocessing

我的程序有几个参数,其中一个名为challenges,它从命令行接收整数值。我想通过将multiprocessing的值传递给自定义方法challenges来使用generation

import multiprocessing

gen = generator.GenParentClass()
mlp = multiprocessing.Pool(processes=multiprocessing.cpu_count())
X, y = mlp.imap_unordered(gen.generation, [args.challenges])

班级generation中的方法GenParentClass有这个简单的签名:

def generation(self, num):
   #some stuff

然而,我收到此错误:

Traceback (most recent call last):
  File "experiments.py", line 194, in <module>
    X, y = mlp.imap_unordered(gen.generation, [args.challenges])
  File "/anaconda/lib/python2.7/multiprocessing/pool.py", line 668, in next
    raise value
cPickle.PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

我不知道如何解决这个问题。一切似乎对我来说都是正确的!!任何帮助,谢谢。

1 个答案:

答案 0 :(得分:1)

multiprocess模块将pickles的参数序列化(imap_unordered)。似乎函数gen.generation是一个实例方法(在类中定义),这意味着它不能被腌制,因此你的错误。

编辑:这是一个可能的解决方法,它定义了类之外的函数,并向该函数添加了其他参数,这些参数使用partial中的itertools填充:

import multiprocessing
from functools import partial

class GenParentClass(object):
    a = None
    b = None
    def __init__(self, a, b):
        self.a = a
        self.b = b

# define this outside of GenParentClass (i.e., top level function)
def generation(num, x, y):
    return x+y+num

gen = GenParentClass(3, 5)
mlp = multiprocessing.Pool(processes=multiprocessing.cpu_count())
R = mlp.imap_unordered(partial(generation, x=gen.a, y=gen.b), [1,2,3])
print([r for r in R])   # prints "[9, 10, 11]"

有关腌制能力的更多信息here

有关functools的更多信息,请访问here

编辑2:如果您使用multiprocess.Pool且函数定义使用限定变量名self.aself.b,则可以在不重写类外的函数的情况下执行此操作,但您赢了'能够检索输出,并且gen2的状态不会改变(完全没有调用函数的目的)。

gen2 = GenParentClass(4, 6)
p = {}
for key in range(5):
    p[key] = multiprocessing.Process(target = GenParentClass.altgen, args = (gen2, key,))
    p[key].start()

for key in p:
    p[key].join()