PicklingError: 无法使用Python进程池执行器对<type 'function'>进行pickle处理

5

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)

以上代码出现了 pickling 错误。我发现原因是我们正在传递实例方法。因此,我们应该取消实例方法的封装。但我无法使其工作。

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


这个问题的解决方案是什么?(链接:https://dev59.com/x18e5IYBdhLWcg3w_-dM) - dano
@dano 我应该在clone.py文件中使用_pickle_method()方法,对吗? - Amby
是的,还有紧随其后的对 copy_reg.pickle 的调用。 - dano
2个回答

4
让我们从概述开始 - 为什么首先会出现错误: 必须在进程或线程之间对数据进行pickle(序列化)以传递它们。具体来说, 方法本身依赖于较低级别的 ,将任务堆叠并将它们传递给线程/进程,并且 要求通过它的所有内容都必须是可pickable的。
问题是,并非所有项目都是可pickable的- pickables列表 - 当试图pickle一个不可pickle的对象时,会收到 异常-这正是你的情况所发生的,你传递了一个不可pickle的实例方法。

对于每个问题,都可以有各种解决方法(这也是本问题的情况) - 对我有效的解决方案是 这里由Dano提供 - 就是让pickle处理方法并将其注册到copy_reg中。


在您的模块clone.py开头添加以下行,使得clone_vm可被序列化(导入copy_regtypes):

def _pickle_method(m):
    if m.im_self is None:
        return getattr, (m.im_class, m.im_func.func_name)
    else:
        return getattr, (m.im_self, m.im_func.func_name)

copy_reg.pickle(types.MethodType, _pickle_method)

其他有用的答案 - 由Alex Martelli, mrule提供,由unutbu提供


1
您需要添加对函数和方法进行 pickling 的支持,才能使其正常工作,正如 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)

这也适用于名称混淆的方法。为使其有效,您需要确保在任何pickle发生之前始终运行此代码。理想的位置是设置文件(如果您使用django)或某个始终在其他代码执行之前导入的包。
致谢:- Steven Bethard (https://bethard.cis.uab.edu/)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接