Python 如何从子流程获取实时输出流?
我试图从正在运行的Python子进程中提取输出。为了简单起见,我创建了一个C可执行文件,它每秒只打印0、1、2等,并无限期运行 我使用的Python脚本,以及其他一些类似想法的变体,似乎都在5分钟内什么也不做,然后一次将300行打印到终端。相反,我试图让它每秒打印一行。使用Python 3.5Python 如何从子流程获取实时输出流?,python,python-3.x,subprocess,pipe,Python,Python 3.x,Subprocess,Pipe,我试图从正在运行的Python子进程中提取输出。为了简单起见,我创建了一个C可执行文件,它每秒只打印0、1、2等,并无限期运行 我使用的Python脚本,以及其他一些类似想法的变体,似乎都在5分钟内什么也不做,然后一次将300行打印到终端。相反,我试图让它每秒打印一行。使用Python 3.5 import subprocess import os import sys from time import sleep def start_program(): args = ['./te
import subprocess
import os
import sys
from time import sleep
def start_program():
args = ['./test_program']
p = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True, bufsize=1)
return p
def print_output(p):
for line in p.stdout:
print(line, end='')
def main():
p = start_program()
print_output(p)
main()
问题是,您的C程序检测到输出不是TTY,因此正在对其进行缓冲。我假设您的C程序是这样的:
#包括
#包括
内部主(空){
对于(int i=0;i<300;++i){
printf(“%d\n”,i);
睡眠(1);
}
}
有两种方法可以修复它:
fflush(stdout)
循环的每次迭代或setvbuf
以在开始时禁用缓冲stdbuf
中,如下所示:args=['stdbuf'、'-oL'、'./test_program']
基本问题由@Joseph Sible Restore Monica描述,但您也可能面临临时阻塞问题。对进程中的行使用
process.stdout.readline()
或。stdout:
使脚本等待process.stdout
中的新行
通过在读取数据之前分析数据的可用性,您可以在无需等待的情况下实时接收和处理数据
主文件:
import subprocess
from time import sleep
process = subprocess.Popen(('python', 'subTest.py'), stdout=subprocess.PIPE)
while True:
sleep(0.7) #do smth
bytes_number = process.stdout.seek(0, 2)
if bytes_number:
print('number of new bytes: ', bytes_number)
process.stdout.seek(0, 0)
print(process.stdout.read(bytes_number))
if process.poll() is not None and not bytes_number:
break
print('done!')
from sys import stdout
from time import sleep
for i in range(10):
sleep(0.2) #do smth
stdout.write(str(i) + '/')
stdout.flush()
如果运行另一个python脚本而不是C-可执行文件,则还需要使用stdout.flush()
(python中的模拟fflush(stdout)
)
子流程文件:
import subprocess
from time import sleep
process = subprocess.Popen(('python', 'subTest.py'), stdout=subprocess.PIPE)
while True:
sleep(0.7) #do smth
bytes_number = process.stdout.seek(0, 2)
if bytes_number:
print('number of new bytes: ', bytes_number)
process.stdout.seek(0, 0)
print(process.stdout.read(bytes_number))
if process.poll() is not None and not bytes_number:
break
print('done!')
from sys import stdout
from time import sleep
for i in range(10):
sleep(0.2) #do smth
stdout.write(str(i) + '/')
stdout.flush()
这是我早些时候尝试过的想法之一,但不幸的是,子流程的stdout不可查找,因此此解决方案在这里不可行。