我可以拆分/合并subprocess.Popen的输出流吗?

时间:2012-01-15 00:46:53

标签: python logging stream subprocess

我正在编写一个与工作流管理器一起使用的包装类。我想以某种方式记录应用程序的输出(通过subprocess.Popen执行的子进程):

    孩子的
  • stdout应该转到日志文件和父母的stdout
  • 孩子的
  • stderr应该转到不同的日志文件,但也转到父母的stdout

即。孩子的所有输出应该最终在stdout上合并(就像subprocess.Popen(..., stderr=subprocess.STDOUT)一样,所以我可以保留stderr来自包装器本身的日志消息。另一方面,孩子的流应该转到不同的文件以允许单独验证。

我尝试使用“Tee”帮助程序类将两个流(stdout和日志文件)绑定在一起,以便Tee.write写入两个流。但是,这不能传递给Popen,因为“subprocess”使用OS级函数进行写入(参见此处:http://bugs.python.org/issue1631)。

我当前的解决方案(下面的代码段,大部分来自here)的问题是stdout上的输出可能不会按正确的顺序出现。

我怎样才能克服这一点?或者我应该使用完全不同的方法? (如果我坚持使用下面的代码,如何选择os.read中的字节数值?)

import subprocess, select, sys, os

call = ... # set this
process = subprocess.Popen(call, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
logs = {process.stdout: open("out.log", "w"), process.stderr: open("err.log", "w")}
done = {process.stdout: False, process.stderr: False}
while (process.poll() is None) or (not all(done.values())):
    ready = select.select([process.stdout, process.stderr], [], [])[0]
    for stream in ready:
        data = os.read(stream.fileno(), 1)
        if data:
            sys.stdout.write(data)
            logs[stream].write(data)
        else:
            done[stream] = True
logs[process.stdout].close()
logs[process.stderr].close()

顺便说一下,使用“fcntl”的this solution对我没用。我还不清楚如何使this solution适应我的情况,所以我没有尝试过。

1 个答案:

答案 0 :(得分:1)

如果设置shell=True,则可以将命令字符串传递给 subprocess ,其中包括管道,重定向和 tee command