Python多进程报错:Can't pickle local object 问题求助
解决多进程Pickling报错:AttributeError: Can't pickle local object '_createenviron..encodekey'
问题本质
这个报错核心是Python多进程间传递的对象无法被Pickle序列化——_createenviron.<locals>.encodekey是嵌套在函数内部的局部对象,而Pickle天生不支持序列化这类局部生成的函数/对象。你贴的简化代码里没直接体现,但肯定是date或者info[t]里包含了这类对象(比如从某个函数内部生成的环境变量相关实例、嵌套函数对象等)。
快速修复方案
方案1:拆出可序列化的基础数据
检查date和info[t]的内容,把里面涉及局部对象的部分替换成字符串、数字、顶层类实例这类可序列化的基础类型。比如如果info里存的是带环境变量的复杂对象,别直接传整个对象,只传需要的具体参数:
# 原来的错误写法 process = Process(target=run_runner, args=[date, info[t]]) # 修改后:提取能被Pickle序列化的参数 needed_data = { 'site_url': info[t].url, 'timeout': info[t].timeout, 'config': info[t].config_str # 确保是字符串而非局部生成的对象 } process = Process(target=run_runner, args=[date, needed_data])
方案2:用Manager共享数据
如果必须传递复杂对象,用multiprocessing.Manager创建跨进程共享的容器,绕开直接Pickle传递的问题:
from multiprocessing import Process, Manager def run_runner(date, info_item): # 直接使用共享过来的数据 do stuff if __name__ == '__main__': with Manager() as manager: # 把原info转成进程共享的列表 shared_info = manager.list(info) processes = [] for t in range(len(sites)): process = Process(target=run_runner, args=[date, shared_info[t]]) processes.append(process) process.start() for p in processes: p.join()
方案3:切换到spawn启动模式
Unix系统默认用fork模式,会继承父进程里的局部对象,而spawn模式会重新启动Python解释器,避免继承这类无法序列化的东西。在代码开头添加设置:
import multiprocessing as mp if __name__ == '__main__': mp.set_start_method('spawn') # 下面是你的多进程代码 processes = [] for t in range(len(sites)): process = Process(target=run_runner, args=[date, info[t]]) processes.append(process) process.start() for p in processes: p.join()
额外提醒
run_runner函数必须定义在模块顶层,不能嵌套在其他函数里——嵌套函数同样无法被Pickle序列化。- 所有传给子进程的参数,要么能被Pickle序列化,要么用Manager这类工具共享。
内容的提问来源于stack exchange,提问作者zicari
相关产品推荐
相关产品推荐

