Subprocess.Popen无输出问题:如何实时获取子进程打印内容?
问题描述
编写了如下主程序代码,预期运行../目录下的test.py,并在捕获KeyboardInterrupt时终止子进程,同时实时看到子进程的print输出,但实际无任何输出:
主程序代码:
from subprocess import Popen, PIPE import os # 原代码漏导入os模块 if os.path.isfile('../'): cmd = os.path.join(os.getcwd(), '../') proc = Popen(["python3", "-m", cmd], stdout=PIPE, stderr=PIPE) progRunning = True while progRunning: try: output, error = proc.communicate() except KeyboardInterrupt: print("Program Forcequit") progRunning = False proc.kill() print('Process finished')
../目录下的测试代码test.py:
from time import sleep while True: sleep(1) print("Hello World")
解决方案
问题出在三个核心点,逐一修正即可:
修正子进程启动逻辑:
os.path.isfile('../')判断错误,../是目录,应该用os.path.isdir()python3 -m用于运行Python模块,不是直接执行脚本,要运行test.py直接指定脚本路径即可- 无需拼接绝对路径,直接用
../test.py就能定位到目标脚本
实时读取输出,避免阻塞:
proc.communicate()会阻塞到子进程结束才返回结果,无法实时获取内容。改为逐行读取子进程的标准输出:用proc.stdout.readline()循环读取,同时判断空行(子进程结束时会返回空)来终止循环。禁用Python输出缓冲:
Python默认会缓冲标准输出,导致子进程的print内容无法实时传到主进程。两种解决方式二选一:- 启动子进程时加
-u参数:python3 -u ../test.py,强制无缓冲输出 - 在子进程的
print里加flush=True:print("Hello World", flush=True)
- 启动子进程时加
修正后的完整代码
主程序:
from subprocess import Popen, PIPE import os if os.path.isdir('../'): # 指定脚本路径,用-u禁用缓冲,text=True让输出以字符串返回 proc = Popen(["python3", "-u", "../test.py"], stdout=PIPE, stderr=PIPE, text=True) progRunning = True try: while progRunning: line = proc.stdout.readline() if not line: progRunning = False break print(line.strip()) except KeyboardInterrupt: print("\nProgram Forcequit") proc.kill() print('Process finished')
测试代码test.py(如果不用-u参数,就用这个版本):
from time import sleep while True: sleep(1) print("Hello World", flush=True)
内容的提问来源于stack exchange,提问作者PythonDudeLmao
相关产品推荐
相关产品推荐

