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
相关产品推荐
相关产品推荐

