【发布时间】: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