【问题标题】:PicklingError: Can't pickle <type 'function'> with python process pool executorPicklingError: Can't pickle <type 'function'> with python process pool executor
【发布时间】:2015-08-12 16:53:46
【问题描述】:

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)

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

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

【问题讨论】:

  • this question 解决问题了吗?
  • @dano 我应该在 clone.py 文件中使用 _pickle_method() 对吗?
  • 是的,紧随其后的是对copy_reg.pickle的调用。

标签: python python-multiprocessing


【解决方案1】:

让我们从概述开始 - 首先出现错误的原因:

multiprocessing 必须要求对数据进行腌制(序列化)以将它们沿进程或线程传递。具体来说,pool 方法本身依赖于较低级别的queue 来堆叠任务并将它们传递给线程/进程,而queue 要求通过它的所有内容都必须是可选的。

问题是,并非所有项目都是可挑选的 - list of pickables - 当一个人试图腌制一个不可挑选的对象时,会得到 PicklingError 异常 - 正是你的情况发生的情况,你通过了一个不可腌制的实例方法。

可以有各种解决方法(每个问题都是如此)- 对我有用的解决方案是 here by Dano - 是让 pickle 处理方法并将其注册到 copy_reg


在模块的开头添加以下行 clone.py 以使 clone_vm 可以选择(执行 import 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 Martellimruleunutbu

【讨论】:

    【解决方案2】:

    您需要添加对酸洗函数和方法的支持,才能如 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/)

    【讨论】:

      猜你喜欢
      • 2017-05-11
      • 2020-08-18
      • 2011-12-13
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 2012-02-06
      • 2016-05-23
      • 2018-06-26
      相关资源
      最近更新 更多