Python multiprocessing 多进程修改传入列表不生效问题咨询
多进程下列表无法跨进程更新的原因与解决方案
核心原因
multiprocessing 启动的子进程与主进程是完全内存隔离的。
当你把普通Python列表li作为参数传给子进程时,multiprocessing会通过pickle序列化把这个列表完整拷贝一份,传入子进程的独立内存空间。子进程内所有对列表的修改,都只会作用在这个拷贝对象上,完全不会同步回主进程的原列表。
你在子进程内打印看到的更新后列表,只是子进程那份拷贝的状态,主进程内存里的原列表从始至终没有被改动过,最终打印自然和预期不符。
单进程逻辑下所有操作都作用在同一块内存的原变量上,修改自然可以被全局感知,这是和多进程机制最本质的区别。
可落地的解决方法
1. 使用multiprocessing提供的跨进程托管共享结构
multiprocessing内置的Manager()可以生成跨进程同步的变量代理,通过这个代理修改的内容会自动同步到所有关联进程,适配你原代码的写法可以改成:
import multiprocessing def read(shared_li, i): name = "char" shared_li[i:i] = [name] print(f"子进程内的列表状态: {list(shared_li)}") def write(i): pass if __name__ == '__main__': i = 1 # 用Manager生成可跨进程同步的列表 with multiprocessing.Manager() as manager: li = manager.list([4]) p1 = multiprocessing.Process(target=read, args=(li, i)) p2 = multiprocessing.Process(target=write, args=(i,)) p1.start() p2.start() p1.join() p2.join() print(f"主进程最终的列表状态: {list(li)}")
运行上述代码,主进程就可以拿到子进程修改后的列表内容。
2. 通过进程间通信把结果回传主进程
如果不需要实时跨进程共享列表状态,只需要等子进程完成修改后统一同步数据,更推荐用通信管道回传结果的方式,性能比全程用托管结构更好:
- 可以用
multiprocessing.Queue作为通信通道,子进程把修改完成的列表放入队列,主进程从队列取出后更新本地变量 - 也可以用
concurrent.futures.ProcessPoolExecutor提交任务,直接接收子进程函数的返回值
用Queue实现的适配写法:
import multiprocessing def read(result_queue, i): name = "char" # 子进程内完成列表修改 local_li = [4] local_li[i:i] = [name] # 将修改结果推入队列,回传给主进程 result_queue.put(local_li) def write(i): pass if __name__ == '__main__': i = 1 li = [4] result_queue = multiprocessing.Queue() p1 = multiprocessing.Process(target=read, args=(result_queue, i)) p2 = multiprocessing.Process(target=write, args=(i,)) p1.start() p2.start() # 主进程接收子进程回传的修改结果 li = result_queue.get() p1.join() p2.join() print(f"主进程最终的列表状态: {li}")
注意事项
- 跨进程共享的变量会引入额外的通信开销,大列表全程用托管结构会明显拉低运行效率,优先选择“子进程完成计算、最后回传结果”的模式
- 多个进程同时写入同一个共享变量时,需要搭配
multiprocessing.Lock加锁,避免出现数据竞态导致的内容错乱
内容的提问来源于stack exchange,提问作者Aparna venugopal
相关产品推荐
相关产品推荐

