Python使用subprocess.run调用子脚本无法实时捕获输出怎么解决?
问题原因
- Python默认输出缓冲策略:当子进程的标准输出没有直接连接终端(比如通过管道被父进程捕获)时,Python会默认开启全缓冲,
print输出的内容会暂存在缓冲区,只有缓冲区满、进程正常退出时才会写入管道。你60秒就强制终止了counting.py进程,缓冲区内容还没来得及刷出,所以父进程拿不到任何输出。 subprocess.run()的执行逻辑:该方法会阻塞等待子进程完全结束后,才会一次性返回所有标准输出内容,就算没有缓冲问题,你也没法在子进程运行过程中实时看到逐行输出,只能等进程结束后拿到全量结果。
修复方案
不需要修改任何子脚本,只需要调整master.py的调用逻辑即可:
- 调用Python解释器时添加
-u参数,强制禁用标准输入输出的缓冲 - 改用
subprocess.Popen逐行读取子进程的实时输出 - 可以直接使用
subprocess自带的超时参数,无需额外引入multiprocessing做超时控制,代码更简洁
修改后的master.py代码如下:
import subprocess import sys from pathlib import Path def run_file(filename, timeout=60): cmd = [sys.executable, "-u", str(Path.cwd() / f"{filename}.py")] try: with subprocess.Popen( cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, # 合并标准错误和标准输出,也可单独处理 bufsize=1, # 开启行缓冲 ) as proc: # 逐行读取输出并打印 for line in proc.stdout: print(line, end="") # 等待进程结束判断返回码 returncode = proc.wait(timeout=timeout) if returncode != 0: print(f"子进程{filename}异常退出,返回码:{returncode}") except subprocess.TimeoutExpired: print("\nTimeout! Killing the process...") proc.kill() proc.wait() except Exception as e: print(f"调用{filename}时出错,执行命令:{cmd}") print(f"错误详情:{e}") if __name__ == '__main__': run_file("counting")
可选适配方案(需修改子脚本)
如果不想在调用时加-u参数,也可以直接修改counting.py的print语句,手动添加flush=True强制刷出缓冲:
print(f"Counting: {i}", flush=True)
运行修改后的代码,就可以实时看到和直接运行counting.py完全一致的逐秒计数输出,60秒超时后会自动终止进程。
内容的提问来源于stack exchange,提问作者lazarea
相关产品推荐
相关产品推荐

