如何从子进程中过滤标准错误

时间:2016-08-28 15:22:42

标签: python subprocess

我使用Popen来运行外部流程。这是一个刻意简单的例子来说明; ls写入标准输出,并写入每个丢失文件的标准错误:

#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE

def test_process(*command):
    process = Popen(command)
    process.communicate()

test_process('ls', '/etc/hosts', 'bad1', 'bad2', 'bad3')

输出如下:

/etc/hosts
ls: cannot access 'bad1': No such file or directory
ls: cannot access 'bad2': No such file or directory
ls: cannot access 'bad3': No such file or directory

但是,我想从标准错误中过滤掉某些行,因此我需要将某些内容传递给stderr构造函数的Popen参数。

根据Python文档(并通过逐步执行IDE中的代码确认),stderr参数只能是PIPEDEVNULL,整数文件描述符或文件 - 像对象包装(有效)文件描述符。我尝试创建一个类并在stderr中传递一个新实例,并想要实现缺少的方法来进行过滤;但这不起作用,因为它的fileno方法必须返回一个实际的文件描述符。

所以我认为我需要传递stderr=PIPE,并在创建的管道的另一端进行过滤。这是我的尝试:

def test_process(*command):
    process = Popen(command, stderr=PIPE)
    output, error = process.communicate()
    if error:
        lines = error.decode().splitlines()
        for line in lines:
            if '2' not in line:
                print(line, file=sys.stderr)

然而,虽然我不希望标准错误包含很多行,但是在运行中过滤它会更优雅。有没有什么方法可以编写一些一次接收一行的Python代码,然后将其丢弃或传递给它?我想我可以创建一个新的子进程来进行过滤,并将另一个Popen链接到第一个上,但这似乎是该任务的重量级。

我当然不想中断正在写入实际控制台的标准输出流,所以我不能一次只读一行标准错误,我可能会这样做标准输出。

有更好的想法吗?

0 个答案:

没有答案