【问题标题】:Can I split/merge output streams of subprocess.Popen?我可以拆分/合并 subprocess.Popen 的输出流吗?
【发布时间】:2012-02-10 14:35:32
【问题描述】:

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

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

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

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

我当前解决方案的问题(下面的代码 sn-p,主要改编自 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()

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

【问题讨论】:

    标签: python logging stream subprocess


    【解决方案1】:

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

    【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2013-12-17
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多