PicklingError:无法用python进程池执行器

时间:2015-08-12 16:53:47

标签: python python-multiprocessing

util.py

def exec_multiprocessing(self, method, args):
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = pool.map(method, args)
        return results

clone.py

def clone_vm(self, name, first_run, host, ip):
    # clone stuff

invoke.py

exec_args = [(name, first_run, host, ip) for host, ip in zip(hosts, ips)]
results = self.util.exec_multiprocessing(self.clone.clone_vm, exec_args)

上面的代码给出了酸洗错误。我发现这是因为我们正在传递实例方法。所以我们应该打开实例方法。但我无法使其发挥作用。

注意:我无法创建顶级方法来避免这种情况。我必须使用实例方法。

2 个答案:

答案 0 :(得分:3)

让我们从概述开始 - 为什么首先出现错误:

<!DOCTYPE html> <html> <head> <title>POST API</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.js"></script> <script type="text/javascript" src="post.js"></script> <script type="text/javascript" src="get.js"></script> </head> <body> <div> <button id="btn1">Check HTTP POST</button> <p> Display sample output from POST API: </p> <p id="one" >wEventId : </p> <p id="two"> </p> </div> <div> <button id="btn2">Get Data</button> <p id="seven"></p> <p id="eight" ></p> <p id="three" ></p> <p id="four" ></p> <p id="five"></p> <p id="six"></p> </div> </body> </html> 必须要求pickle(序列化)数据以沿进程或线程传递它们。具体而言,multiprocessing方法本身依赖于较低级别的pool来堆叠任务并将它们传递给线程/进程,queue要求通过它的所有内容都必须是可选的。

问题是,并非所有项目都可以选择 - list of pickables - 并且当一个人试图挑选一个无法解决的对象时,会获得 queue 异常 - 确切地说是例如,您传递了一个不可选择的实例方法。

可以有各种解决方法(就像每个问题的情况一样) - 对我有用的解决方案是here by Dano - 是让PicklingError处理方法并将其注册到{{3} }。

在模块pickle的开头添加以下行,以使clone.py可选择(clone_vm importcopy_reg}:

types

其他有用的答案 - copy_regAlex Martellimrule

答案 1 :(得分:1)

你需要为Nabeel Ahmed指出的酸洗功能和方法添加支持。但他的解决方案不适用于name-mangled方法 -

import copy_reg
import types

def _pickle_method(method):
    attached_object = method.im_self or method.im_class
    func_name = method.im_func.func_name

    if func_name.startswith('__'):
        func_name = filter(lambda method_name: method_name.startswith('_') and method_name.endswith(func_name), dir(attached_object))[0]

    return (getattr, (attached_object, func_name))

copy_reg.pickle(types.MethodType, _pickle_method)

这也适用于名称受损的方法。为此,您需要确保在任何酸洗发生之前始终运行此代码。理想的位置是设置文件(如果您使用的是django)或一些在执行其他代码之前始终导入的包。

致谢: - Steven Bethard(https://bethard.cis.uab.edu/