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

使用Python Multiprocessing处理Pydantic BaseModel报错求助

解决multiprocessing.Manager共享Pydantic BaseModel对象的AttributeError问题

你遇到的AttributeError: '__signature__' attribute of 'data_object' is class-only错误,是因为Pydantic的BaseModel自带的__signature__是类专属属性,multiprocessing.Manager在生成代理对象时会尝试访问该属性,而代理机制无法正确处理这类类属性导致的。下面提供两种可行的解决思路:

方法一:用包装类封装Pydantic对象

通过自定义一个简单的包装类,把Pydantic Model实例包裹起来,让Manager注册这个包装类,避免直接操作Pydantic Model类。包装类提供 getter/setter 方法来操作内部的Pydantic对象:

import pydantic
from typing import Optional
import multiprocessing
from multiprocessing.managers import BaseManager

class DataObject(pydantic.BaseModel):
    url: str
    downloaded: Optional[bool] = False

# 包装类用于进程间共享
class SharedDataObject:
    def __init__(self, url: str, downloaded: Optional[bool] = False):
        self.model = DataObject(url=url, downloaded=downloaded)
    
    def get_url(self):
        return self.model.url
    
    def set_downloaded(self, value: bool):
        self.model.downloaded = value
    
    def get_downloaded(self):
        return self.model.downloaded

class CustomManager(BaseManager):
    pass

def downloader(single_data: SharedDataObject):
    single_data.set_downloaded(True)

if __name__ == '__main__':
    # 单进程测试(正常运行)
    just_one_object = DataObject(url='url1')
    print(just_one_object.downloaded)
    just_one_object.downloaded = True
    print(just_one_object.downloaded)

    # 多进程共享逻辑
    CustomManager.register('SharedDataObject', SharedDataObject)
    CustomManager.register('list', list)
    with CustomManager() as manager:
        shared_single_object = manager.SharedDataObject(url='url2')
        print(shared_single_object.get_downloaded())
        downloader(shared_single_object)
        print(shared_single_object.get_downloaded())

        managed_list = manager.list([manager.SharedDataObject(url=f'url{v}') for v in range(5)])

        pool = multiprocessing.Pool(processes=5)
        pool.map(downloader, managed_list)
        pool.close()
        pool.join()

        # 输出最终状态
        for item in managed_list:
            print(f"URL: {item.get_url()}, Downloaded: {item.get_downloaded()}")

方法二:避免共享对象,用返回结果更新状态

放弃进程间共享对象的思路,改用Pool.map的返回值来获取处理后的Pydantic对象。这种方式更简单,也避免了共享对象带来的同步问题:

import pydantic
from typing import Optional
import multiprocessing

class DataObject(pydantic.BaseModel):
    url: str
    downloaded: Optional[bool] = False

def downloader(single_data: DataObject) -> DataObject:
    # 模拟下载操作,修改状态
    single_data.downloaded = True
    return single_data

if __name__ == '__main__':
    # 单进程测试
    just_one_object = DataObject(url='url1')
    print(just_one_object.downloaded)
    just_one_object = downloader(just_one_object)
    print(just_one_object.downloaded)

    # 多进程批量处理
    task_list = [DataObject(url=f'url{v}') for v in range(5)]

    pool = multiprocessing.Pool(processes=5)
    result_list = pool.map(downloader, task_list)
    pool.close()
    pool.join()

    # 打印处理后的结果
    for item in result_list:
        print(f"URL: {item.url}, Downloaded: {item.downloaded}")

错误原因说明

Pydantic的BaseModel类会自动生成__signature__类属性,用于参数校验和类型提示。multiprocessing.Manager在注册类并生成跨进程代理对象时,会尝试复制类的属性,但__signature__是仅属于类的属性,无法被代理对象正确访问,因此触发了AttributeError。

内容的提问来源于stack exchange,提问作者Dalada

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:23:18