You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 07:45:06