我正在编写一个与工作流管理器一起使用的包装类。我想以某种方式记录应用程序的输出(通过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适应我的情况,所以我没有尝试过。