我使用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
参数只能是PIPE
,DEVNULL
,整数文件描述符或文件 - 像对象包装(有效)文件描述符。我尝试创建一个类并在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
链接到第一个上,但这似乎是该任务的重量级。
我当然不想中断正在写入实际控制台的标准输出流,所以我不能一次只读一行标准错误,我可能会这样做标准输出。
有更好的想法吗?