如何从子流程中获取实时输出流?

How to get live stream of output from a subprocess?

我正在尝试从 运行 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 = ['./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 程序是这样的:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    for(int i = 0; i < 300; ++i) {
        printf("%d\n", i);
        sleep(1);
    }
}

有两种方法可以修复它:

  1. 编辑您的 C 程序以执行 fflush(stdout); 循环的每次迭代或 setvbuf 以在开始时禁用缓冲
  2. 编辑您的 Python 程序以将您的 C 程序包装在 stdbuf 中,如下所示:args = ['stdbuf', '-oL', './test_program']

基础问题已由 @Joseph Sible-Reinstate Monica 描述,但您也可能面临临时阻塞问题。使用 process.stdout.readline()for line in process.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!')

如果您 运行 另一个 python 脚本而不是 C-executable 您还需要使用 stdout.flush()(模拟 Python 中的 fflush(stdout)) .

子进程文件:

from sys import stdout
from time import sleep

for i in range(10):
    sleep(0.2) #do smth
    stdout.write(str(i) + '/')
    stdout.flush()