基于抽象类的类使用multiprocessing时出现AttributeError问题
问题根源
为啥不用抽象类时好好的,一继承ABC就报属性找不到?核心是抽象基类的元类(ABCMeta)会修改实例的内部结构,导致pathos用的dill序列化工具没能完整保存/恢复你的实例属性。
多进程池传递对象时,会把对象序列化打包,子进程再反序列化重建。普通类的实例结构简单,dill能轻松搞定,但ABC的元类会给实例加一些额外的约束逻辑,搞乱了默认的序列化流程,结果子进程里重建的MyPlot对象根本没带上series1这类属性,自然报错。
解决办法
1. 手动控制序列化/反序列化
给MyPlot加两个方法,自己指定要保存的属性,绕过ABC元类的干扰:
from abc import ABC, abstractmethod import pathos.multiprocessing as mp import matplotlib.pyplot as plt class GenericPlot(ABC): @abstractmethod def plot(self): pass class MyPlot(GenericPlot): def __init__(self, data): self.series1 = data # 你的其他初始化代码 def plot(self): plt.plot(self.series1) # 保存或显示图形的逻辑 # 告诉dill要保存哪些属性 def __getstate__(self): return self.__dict__ # 告诉子进程怎么恢复属性 def __setstate__(self, state): self.__dict__.update(state) # 测试代码 def run_plot(plot_obj): plot_obj.plot() if __name__ == "__main__": datasets = [[1,2,3], [4,5,6], [7,8,9]] plot_instances = [MyPlot(ds) for ds in datasets] with mp.Pool(3) as pool: pool.map(run_plot, plot_instances)
2. 别在主函数块里定义类
如果你的GenericPlot或MyPlot是写在if __name__ == "__main__"里面的,子进程导入模块时根本找不到这些类的定义,反序列化出来的对象会残缺,也会报属性错。把类的定义移到模块顶层(主函数外面)。
3. 备选:用普通基类代替ABC
如果只是想统一接口,不需要ABC强制检查抽象方法,把GenericPlot改成普通类就行,这样就不会有元类的问题:
class GenericPlot: def plot(self): raise NotImplementedError("必须实现plot方法")
新手必记的多进程要点
跨进程传递的对象必须能被完整序列化——不是所有类都能直接扔进程池里,带特殊元类(比如ABC、ORM模型的元类)的类,大概率要自己处理序列化逻辑。
内容的提问来源于stack exchange,提问作者darf
相关产品推荐
相关产品推荐

