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

multiprocessing调用map报错cannot pickle MySQL连接对象TypeError

问题原因

Python multiprocessing 模块向进程池投递任务时,会通过pickle对所有传递的对象做序列化,跨进程传输后再反序列化为子进程内的可用对象。
调用p.map(self.GetServerData, self.data)时,传入的是绑定到当前类实例的方法,序列化这个方法会连带序列化绑定的self实例本身。类实例中保存了提前初始化的_mysql_connector.MySQL数据库连接对象,这类对象是底层C实现的网络连接句柄,属于进程独占的内核资源,本身不支持pickle序列化,因此触发报错。

额外说明:就算强行绕过序列化检查,主进程创建的数据库连接、socket、打开的文件句柄这类资源也无法在子进程中正常使用,跨进程共享这类资源本身就是不可行的。

修复方案

根据业务场景选以下任意一种方案即可:

  • 方案1:为每个子进程单独初始化数据库连接
    利用进程池的initializer参数,在每个子进程启动时独立创建属于自己的MySQL连接,完全避免把主进程的连接对象传递到子进程。示例代码:
    from multiprocessing import Pool
    import mysql.connector
    
    THREADS_COUNT = 20
    # 子进程全局变量存储独立数据库连接
    _sub_process_db = None
    
    def _init_sub_worker(db_config):
        # 每个子进程启动时执行,创建仅当前子进程可用的数据库连接
        global _sub_process_db
        _sub_process_db = mysql.connector.connect(**db_config)
    
    def _get_server_data_proxy(data_item):
        # 代理函数,子进程调用时使用自身的数据库连接执行业务逻辑
        # 可将原self.GetServerData中依赖数据库的逻辑迁移到此处
        # 若需要调用原类方法,可将类实例中不包含数据库连接的部分作为参数传入
        pass
    
    if __name__ == "__main__":
        # 初始化进程池时传入初始化函数和数据库配置参数
        p = Pool(
            THREADS_COUNT,
            initializer=_init_sub_worker,
            initargs=(your_db_config_dict,)
        )
        raw_stats = p.map(_get_server_data_proxy, self.data)
        p.close()
        p.join()
    
  • 方案2:自定义类的序列化/反序列化逻辑
    如果不想拆分原有类的方法,可以通过实现类的__getstate__和__setstate__魔法方法,自定义序列化时排除不可序列化的数据库连接,在子进程反序列化实例时自动重建连接。示例代码:
    import mysql.connector
    
    class YourDataServiceClass:
        def __init__(self, db_config):
            self.db_config = db_config
            # 主进程初始化时可正常创建连接供主进程使用
            self.db_conn = mysql.connector.connect(**self.db_config)
            # 其他原有初始化逻辑
    
        def __getstate__(self):
            # 序列化实例时,复制实例属性字典,移除不可序列化的数据库连接对象
            state = self.__dict__.copy()
            del state["db_conn"]
            return state
    
        def __setstate__(self, state):
            # 子进程反序列化恢复实例时,重建属于当前子进程的数据库连接
            self.__dict__.update(state)
            self.db_conn = mysql.connector.connect(**self.db_config)
    
        def GetServerData(self, data_item):
            # 原有业务逻辑无需修改,正常使用self.db_conn即可
            pass
    
  • 避坑提示:不要在主进程中提前创建数据库连接后再把实例传入进程池,所有跨进程传递的对象必须是可序列化的,进程独占的IO资源必须在所属进程内单独创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:45:34