多进程加载模块后全局变量出现双值问题求助
多进程加载模块后全局变量出现双值问题求助
问题描述
你现在遇到的情况肯定特别困惑吧:通过multiload.py用Popen启动了两个独立的Python进程——module2.py和module1.py,想让module1调用module2的函数修改module2里的全局变量PLvar,结果却发现module2自身循环里打印的PLvar一直停留在初始值6,而module1里打印的module2.PLvar却跟着循环在变化,就好像同一个变量有两个不同的“分身”一样。
先把你贴的代码整理成清晰的格式:
你的代码文件
multiload.py
from subprocess import Popen from time import sleep t=1 Popen(['python3', 'module2.py']) sleep(t) Popen(['python3', 'module1.py']) sleep(t)
module1.py
import time print("to load") import module2 print("loaded") i=0 while True: module2.changeVar(i) print("module1",i) print("module2.PLvar",module2.PLvar) i+=1 time.sleep(3)
module2.py
import time PLvar = 6 def changeVar(v): global PLvar PLvar = v print("changeVar m2",PLvar) # this PLvar is changing with the loop in module1 def main(): while True: global PLvar print ("while m2",PLvar) # this PLvar is stuck at 6 (as assigned in line 3) time.sleep(3) print("module2",__name__) if (__name__=="__main__"): print("module 2 main started") main()
问题根源
其实这是多进程的内存隔离特性在搞鬼!你用Popen启动的是两个完全独立的Python进程,它们各自拥有独立的内存空间:
- 第一个
Popen启动的是module2.py的独立进程,它的PLvar初始值是6,之后就一直在自己的内存空间里循环打印这个值。 - 第二个
Popen启动的是module1.py的独立进程,当module1里import module2时,它其实是在自己的进程空间里加载了一份module2的副本——也就是说,module1里调用的module2.changeVar修改的是自己进程内那份module2副本的PLvar,和第一个进程里的module2完全是两个不相干的“个体”!
这就是为什么会出现“两个不同值”的原因——它们根本不是同一个变量,只是名字相同的两个独立变量,分别待在两个完全隔离的进程里。
解决方案
如果要让两个进程之间共享变量或者通信,不能直接通过模块全局变量来操作,得用**进程间通信(IPC)**的方式,给你推荐几种适合你场景的方案:
- 用
multiprocessing的共享内存:比如Value或Array,可以创建父子进程共享的变量。 - 用消息队列:比如
multiprocessing.Queue,让module1把要设置的值发送给module2,module2收到后自己修改内部的PLvar。 - 用管道:
multiprocessing.Pipe,实现双向的进程通信。
这里给你举个用Queue实现的简单例子,刚好匹配你的需求:
修改后的multiload.py(用multiprocessing管理进程)
from multiprocessing import Process, Queue import module2 import module1 from time import sleep def run_module2(q): module2.main(q) def run_module1(q): module1.run(q) if __name__ == "__main__": q = Queue() p2 = Process(target=run_module2, args=(q,)) p1 = Process(target=run_module1, args=(q,)) p2.start() sleep(1) p1.start() p2.join() p1.join()
修改后的module1.py
import time def run(q): print("to load") i=0 while True: # 把要设置的值发送给module2的队列 q.put(i) print("module1",i) i+=1 time.sleep(3)
修改后的module2.py
import time PLvar = 6 def main(q): global PLvar print("module 2 main started") while True: # 检查队列有没有新消息,有的话就更新PLvar if not q.empty(): PLvar = q.get() print("changeVar m2",PLvar) print ("while m2",PLvar) time.sleep(3) print("module2",__name__) if (__name__=="__main__"): from multiprocessing import Queue main(Queue())
这样修改后,module1通过队列把数值传递给module2,module2自己从队列里取消息并更新内部的PLvar,就能实现你想要的“两个进程共享变量更新”的效果啦!
备注:内容来源于stack exchange,提问作者Plem
相关产品推荐
相关产品推荐

