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

Ubuntu22.04升级后Python3.8 subprocess输出异常求助

问题原因及修复方案

问题原因

  • 你使用了stdout=subprocess.PIPE参数,该参数会将子进程的输出捕获到内存缓冲区中,只有当子进程完全执行结束后,才能通过proc.stdout获取输出内容,因此无法实时显示。
  • Ubuntu 22.04系统层面的输出缓冲策略有所调整,即使是Python 3.8环境,子进程在管道模式下默认会采用块缓冲而非行缓冲,进一步加剧了输出无法实时刷新到终端的问题。

修复方案

根据你的需求(实时输出优先,按需选择是否捕获输出),提供以下几种解决方案:

方案1:直接让子进程输出到终端(无需捕获输出)

如果不需要在代码中处理子进程的输出,直接移除stdout=subprocess.PIPE参数,子进程的输出会直接实时打印到父进程的终端:

import subprocess

def main():
    # 移除stdout=PIPE,子进程输出直接流向终端
    proc = subprocess.run(["echo", "test"], check=True)
    print('-------')
    print("FINISH")

if __name__ == "__main__":
    main()

方案2:捕获输出同时实时显示

如果需要在代码中处理输出,同时要保证实时显示,改用subprocess.Popen配合循环逐行读取输出:

import subprocess

def main():
    # 使用Popen启动进程,text=True将输出转为字符串(二进制输出可去掉该参数)
    proc = subprocess.Popen(["echo", "test"], stdout=subprocess.PIPE, text=True)
    
    # 逐行读取并实时打印
    for line in proc.stdout:
        print(line, end='')  # end=''避免重复添加换行符
    
    # 等待进程结束并检查返回码
    proc.wait()
    if proc.returncode != 0:
        raise subprocess.CalledProcessError(proc.returncode, proc.args)
    
    print('-------')
    print("FINISH")

if __name__ == "__main__":
    main()

方案3:强制子进程使用行缓冲(针对Docker/Git等外部命令)

对于Docker、Git这类本身可能采用块缓冲的外部工具,可借助Linux的stdbuf命令强制其使用行缓冲,确保实时输出:

import subprocess

def main():
    # -oL 强制stdout行缓冲,-eL 强制stderr行缓冲(按需添加)
    proc = subprocess.run(["stdbuf", "-oL", "docker", "build", "."], check=True)
    print('-------')
    print("FINISH")

if __name__ == "__main__":
    main()

内容的提问来源于stack exchange,提问作者paul23

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:20:59