Python subprocess启动脚本时无法访问函数全局变量问题
问题根本原因
你现在的代码逻辑存在两个核心错误,导致全局变量无法在函数外访问:
- 跨进程内存不共享:
subprocess.Popen启动的A.py是独立的操作系统进程,Python的全局变量仅在当前进程的内存空间内生效。A.py中导入B模块调用reciv_func时,修改的是A进程自身内存里加载的B模块变量,和B主进程里的a1、b2、c3完全无关,B主进程里的这三个变量自始至终没有被赋值。 - 你当前A.py的协程里写了
while True死循环,哪怕同进程运行,也会一直阻塞在收websocket消息的逻辑里,永远不会执行到后续启动C.py的代码;另外你定义reciv_func时漏写了def关键字,运行会直接触发语法错误。
修复方案
根据你的需求选一种实现即可:
方案1:同进程运行A的逻辑(最简便,无跨进程开销)
不需要开subprocess跑A.py,直接在B.py里导入A的协程函数同进程运行,全局变量可以正常生效,修改示例如下:
- 先修改A.py,拿到目标值后就跳出循环结束协程,不要无限死循环:
import asyncio import json import websockets import B async def main(): url = 'my_url' async with websockets.connect(url) as client: while True: data = json.loads(await client.recv())['data'] # 拿到需要的三个值之后传给B的接收函数,直接跳出循环结束 val = data['x']['y']['z'] B.reciv_func(val[0], val[1], val[2]) break if __name__ == "__main__": asyncio.run(main())
- 再修改B.py,补全函数定义,直接调用A的主逻辑:
import subprocess import asyncio from A import main as A_main # 先给全局变量初始化,避免未定义报错 a1 = None b2 = None c3 = None # 补全def关键字 def reciv_func(a,b,c): global a1 global b2 global c3 a1 = a b2 = b c3 = c if __name__ == "__main__": # 同进程运行A的逻辑,阻塞直到拿到值 asyncio.run(A_main()) # 这里可以正常访问a1、b2、c3,再启动C subprocess.Popen('python C.py', shell=True)
方案2:保留独立进程架构,用进程间通信传值
如果一定要用subprocess启动独立的A.py进程,就不能靠导入模块调用函数的方式传值,可以通过标准输出传递拿到的三个参数,修改示例如下:
- 修改A.py,拿到值后打印到标准输出再退出:
import asyncio import json import websockets async def main(): url = 'my_url' async with websockets.connect(url) as client: while True: data = json.loads(await client.recv())['data'] a,b,c = data['x']['y']['z'] # 用特殊分隔符拼接三个值打印,之后直接退出 print(f"{a}|||{b}|||{c}") break if __name__ == "__main__": asyncio.run(main())
- 修改B.py,捕获A进程的标准输出解析参数:
import subprocess if __name__ == "__main__": # 启动A进程时配置捕获标准输出 proc = subprocess.Popen('python A.py', shell=True, stdout=subprocess.PIPE, text=True) # 阻塞等待A执行完成,读取输出 stdout, _ = proc.communicate() # 解析拿到三个值 a1, b2, c3 = stdout.strip().split("|||") # 拿到值后再启动C subprocess.Popen('python C.py', shell=True)
内容的提问来源于stack exchange,提问作者Aanjay
相关产品推荐
相关产品推荐

