PicklingError:无法使用python进程池执行程序对<type'function'>进行酸洗

Amb*_*mby 5 python python-multiprocessing

实用程序

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

clone.py

def clone_vm(self, name, first_run, host, ip):
    # clone stuff
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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

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

Nab*_*med 4

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

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

问题是,并非所有项目都是可挑选的 -可挑选的列表- 当一个人尝试腌制一个不可腌制的对象时,会得到异常PicklingError- 正是您的情况发生的情况,您传递了一个不可腌制的实例方法。

可以有多种解决方法(每个问题都是如此) - 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)
Run Code Online (Sandbox Code Playgroud)

其他有用的答案 - Alex Martellimruleunutbu