You need to enable JavaScript to run this app. Python多进程使用partial()时抛出ForkingPickler错误如何修复
优惠活动
大模型
产品
解决方案
定价
更多

Python多进程使用partial()时抛出ForkingPickler错误如何修复

问题排查与修复方案

报错根因

该ForkingPickler序列化错误本质是多进程通信时,待序列化的对象中包含了不可被pickle的自定义类实例。你认为入参都是原生字符串,但实际存在隐藏的不可序列化对象进入了序列化流程,常见触发原因有两个:

  1. Entrez.esearch返回的ID列表元素并非纯原生字符串,而是Entrez自定义的XML节点类实例,这类实例序列化时缺少构造必需的tag和attributes参数,触发报错
  2. Linux系统默认使用fork模式启动多进程,主进程调用Entrez接口后产生的全局内存状态会被继承到子进程,其中Entrez依赖的XML解析类实例无法被正确序列化

可行修复步骤

  • 先修正代码中隐藏的低级逻辑错误
    你当前get_doi函数内存在重复调用read()的错误,会引发后续运行异常,先修正:
    # 原错误写法
    docsum_handle = efetch(db="pubmed", id=pim, retmode='text', rettype='docsum').read()
    docsum = docsum_handle.read()
    
    # 修正后写法,efetch调用read()已经返回字符串,无需二次调用
    docsum = efetch(db="pubmed", id=pim, retmode='text', rettype='docsum').read()
    
  • 修改多进程启动模式,规避fork的状态继承问题
    在if __name__ == '__main__'代码块首行添加启动方式配置,改用spawn模式启动进程:
    if __name__ == '__main__':
        import multiprocessing as mp
        mp.set_start_method('spawn') # 新增此行
        # 后续原有代码
    
  • 强制转换ID列表为原生字符串类型
    拿到ID列表后统一转成Python原生字符串,彻底排除Entrez自定义类型的影响:
    pim_list = get_pim_with_regex_list(keywords)
    pim_list = [str(pmid) for pmid in pim_list] # 新增此行做类型转换
    
  • 更优替代方案:改用多线程实现
    爬虫属于IO密集型任务,大部分时间在等待网络响应,多线程的运行效率不低于多进程,还能完全规避序列化问题,替换代码如下:
    if __name__ == '__main__':
        from functools import partial
        from concurrent.futures import ThreadPoolExecutor
        import multiprocessing as mp
    
        keywords = ["keyword1", "keyword2"]
        pim_list = get_pim_with_regex_list(keywords)
        pim_list = [str(pmid) for pmid in pim_list]
        regex = "keyword1 keyword2"
    
        worker_fn = partial(get_doi, regex=regex)
        # 线程数可以设为CPU核心数的2-4倍,充分利用IO等待时间
        with ThreadPoolExecutor(max_workers=mp.cpu_count()*2) as pool:
            entries = list(pool.map(worker_fn, pim_list))
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 02:12:01