asyncio.create_subprocess_shell无法并行运行多个子进程的问题求助
asyncio.create_subprocess_shell无法并行运行多个子进程的问题求助
嗨,我来帮你排查这个问题~
你现在遇到的“任务串行执行”的现象,其实并不是asyncio没有并发启动子进程,而是子进程的输出缓冲区被填满导致进程阻塞了,具体原因和解决方法如下:
问题根源
当你给create_subprocess_shell设置了stdout=asyncio.subprocess.PIPE和stderr=asyncio.subprocess.PIPE时,子进程的标准输出/错误会被写入到管道缓冲区中。Linux系统的管道缓冲区默认大小有限(通常是64KB左右),如果你的C++程序输出大量内容,缓冲区很快就会被填满,这时候子进程会暂停运行,直到缓冲区的数据被读取——而你的代码里只调用了await proc.wait(),没有去读取管道里的内容,第一个子进程就会被卡住,看起来就像所有任务都在串行等待它完成。
解决方案
根据你是否需要保留子进程的输出,有两种处理方式:
1. 不需要保留输出:重定向到/dev/null
如果不需要子进程的输出内容,可以直接把stdout和stderr重定向到DEVNULL,这样就不会出现缓冲区阻塞的问题:
async def run_bash_command(command: str) -> None: print(command) proc = await asyncio.create_subprocess_shell( command, stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL) await proc.wait()
2. 需要保留输出:异步读取管道内容
如果需要获取子进程的输出,要在等待进程结束前,异步读取stdout和stderr的内容,避免缓冲区被填满:
async def run_bash_command(command: str) -> None: print(command) proc = await asyncio.create_subprocess_shell( command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE) # 同时异步读取标准输出和错误,避免管道阻塞 stdout, stderr = await asyncio.gather(proc.stdout.read(), proc.stderr.read()) # 等待进程完成 await proc.wait() # 这里可以按需处理输出内容,比如打印或保存 # print(f"命令 {command} 的输出:\n{stdout.decode()}") # if stderr: # print(f"命令 {command} 的错误:\n{stderr.decode()}")
验证说明
修改后,asyncio会同时启动所有10个子进程(它们作为独立的系统进程并行运行),事件循环会异步调度每个任务的等待和读取操作,不会再出现串行阻塞的情况,完全符合你想要的异步集成需求。
备注:内容来源于stack exchange,提问作者Illia Zalizniak
相关产品推荐
相关产品推荐

