持续处理来自子进程的大量 stdout 和 stderr

Continuously process large amounts of stdout and stderr from a child process

关于如何使用子进程处理输出、异步 IO 以及避免使用 PIPE 死锁,Stack Overflow 上有很多很好的答案。不过,有些事情并没有让我沉迷;我需要一些关于如何完成以下任务的指导。

我想从我的 python 程序中 运行 一个子进程。子进程会生成大量标准输出,如果出现问题,还会生成一些标准错误。子流程本身大约需要 20 分钟才能完成。对于生成的输出和错误,我希望能够将其记录到终端,并将其写入日志文件。

做后者很容易。我刚打开两个文件,然后在 Popen 对象上设置为 stdout 和 stderr。但是,同时将输出捕获为行以便我可以将它们连续打印到终端让我很烦恼。我在想我可以使用 poll() 方法来连续轮询。尽管如此,我仍然需要对 stdout 和 stderr 使用 PIPE,并对它们调用 read() ,这将阻塞直到 EOF。

我想我想要完成的是:

start the subprocess
    while process is still running
        if there are any lines from stdout
           print them and write them to the out log file
        if there are any lines from stderr
           print them and write them to the err log file
        sleep for a little bit

这看起来合理吗?如果是这样,有人可以解释如何在不阻塞的情况下在此处实现 'if' 部分。

谢谢

这是我的 select.select 版本:

子进程(foo.py):

import time
import sys

def foo(): 
    for i in range(5): 
        print("foo %s" %i, file=sys.stdout, )#flush=True
        sys.stdout.flush()
        time.sleep(7)
foo() 

主要:

import subprocess as sp
import select
proc= sp.Popen(["python", "foo.py"], stderr=sp.PIPE, stdout=sp.PIPE)
last_line = "content"
while last_line: 
    buff = select.select([proc.stdout], [], [], 60)[0][0]
    if not buff:
        print('timed out') 
        break 
    last_line = buff.readline() 
    print(last_line)