如何使用Popen同时写入stdout和日志文件?


问题内容

我正在使用Popen调用不断将其stdout和stderr写入日志文件的shell脚本。是否有任何方法可以同时连续(向屏幕)输出日志文件,或者使Shell脚本同时写入日志文件和stdout?

我基本上想在Python中做这样的事情:

cat file 2>&1 | tee -a logfile #"cat file" will be replaced with some script

再次,这会将stderr / stdout一起传送到tee,这会将它同时写入stdout和我的日志文件。

我知道如何在Python中将stdout和stderr写入日志文件。我遇到的问题是如何将这些复制到屏幕上:

subprocess.Popen("cat file", shell=True, stdout=logfile, stderr=logfile)

当然,我可以这样做,但是如果没有tee和shell文件描述符重定向,有没有办法做到这一点?

subprocess.Popen("cat file 2>&1 | tee -a logfile", shell=True)

问题答案:

您可以使用管道从程序的标准输出读取数据并将其写入所需的所有位置:

import sys
import subprocess

logfile = open('logfile', 'w')
proc=subprocess.Popen(['cat', 'file'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in proc.stdout:
    sys.stdout.write(line)
    logfile.write(line)
proc.wait()

更新

在python
3中,该universal_newlines参数控制管道的使用方式。如果为False,则管道读取返回bytes对象,并且可能需要解码(例如line.decode('utf-8'))以获取字符串。如果True,python为您解码

在版本3.3中进行了更改:当Universal_newlines为True时,该类使用编码locale.getpreferredencoding(False)而不是locale.getpreferredencoding()。有关此更改的更多信息,请参见io.TextIOWrapper类。