在 Python 中使用 multiprocessing.Pool 和返回自定义对象的函数

Posted

技术标签:

【中文标题】在 Python 中使用 multiprocessing.Pool 和返回自定义对象的函数【英文标题】:Using multiprocessing.Pool in Python with a function returning custom object 【发布时间】:2021-09-20 12:35:24 【问题描述】:

我正在使用 multiprocessing.Pool 来加速计算,因为我多次调用一个函数,然后整理结果。这是我的代码的 sn-p:

import multiprocessing
from functools import partial

def Foo(id:int,constant_arg1:str, constant_arg2:str):
    custom_class_obj = CustomClass(constant_arg1, constant_arg2)
    custom_class_obj.run() # this changes some attributes of the custom_class_obj
    
    if(something):
       return None
    else:
       return [custom_class_obj]



def parallel_run(iters:int, a:str, b:str):
  pool = multiprocessing.Pool(processes=k)

  ## create the partial function obj before passing it to pool
  partial_func = partial(Foo, constant_arg1=a, constant_arg2=b)

  ## create the variable id list
  iter_list = list(range(iters))
  all_runs = pool.map(partial_func, iter_list)
 
  return all_runs

这会在多处理模块中引发以下错误:

multiprocessing.pool.MaybeEncodingError: Error sending result: '[[<CustomClass object at 0x1693c7070>], [<CustomClass object at 0x1693b88e0>], ....]'
Reason: 'TypeError("cannot pickle 'module' object")'

我该如何解决这个问题?

【问题讨论】:

您需要使您的自定义类可腌制。但是,该错误表明您正在尝试返回 module,而不是自定义类。 我正在返回一个 CustomClass 对象(如错误消息中“结果”后显示的列表所示)。但是,有没有办法将 Pool 用于不可腌制的类? 您将不得不发布您的CustomClass。见How to create a Minimal, Reproducible Example。 【参考方案1】:

我能够使用不可腌制类的最小示例来复制错误消息。该错误基本上表明您的类的实例无法腌制,因为它包含对模块的引用,并且模块不可腌制。您需要梳理CustomClass 以确保实例不包含打开文件句柄、模块引用等内容。如果您需要这些内容,您应该使用__getstate____setstate__ 到customize the pickle and unpickle process .

您的错误的提炼示例:

from multiprocessing import Pool
from functools import partial

class klass:
    def __init__(self, a):
        self.value = a
        import os
        self.module = os #this fails: can't pickle a module and send it back to main process

def foo(a, b, c):
    return klass(a+b+c)

if __name__ == "__main__":
    with Pool() as p:
        a = 1
        b = 2
        bar = partial(foo, a, b)
        res = p.map(bar, range(10))
    print([r.value for r in res])

【讨论】:

感谢您的回答!是的,我的班级确实有模块引用。事实上,它明确包含一个“程序”类对象,该对象内部包含一个 python 程序文件。但是为类设置 getstatesetstate 函数被证明是很棘手的。是否有使用“dill”序列化程序的替代解决方案? 我还没有这样做,但一个廉价的黑客可能是调用dill__getstate__ 中序列化self 并在__setstate__ 中反序列化。还有pathos 库我也没有使用过,但我知道它在某些事情上使用dill 也可以this

以上是关于在 Python 中使用 multiprocessing.Pool 和返回自定义对象的函数的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中使用 multiprocessing.Pool 和返回自定义对象的函数

python多进程multiprocessing

Python多进程multiprocessing

如何在 Python 中使用 multiprocessing.pool 创建全局锁/信号量?

python multiprocessing模块 介绍

11.python并发入门(part9 多线程模块multiprocessing基本用法)