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

Hen*_*rik 7 python logging subprocess stream

我正在编写一个与工作流管理器一起使用的包装类.我想以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).

我当前的解决方案(下面的代码片段,主要是从这里调整)的问题是输出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()
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这个使用"fcntl"的解决方案对我没用.我还不知道如何使这个解决方案适应我的情况,所以我没有尝试过.

Ray*_*ger 1

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