You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于抽象类的类使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:20:08