如何使用 Popen 同时写入标准输出和记录文件?
问题描述
我正在使用 Popen 调用一个不断将其标准输出和标准错误写入日志文件的 shell 脚本.有没有办法同时连续输出日志文件(到屏幕上),或者让shell脚本同时写入日志文件和stdout?
I am using Popen to call a shell script that is continuously writing its stdout and stderr to a log file. Is there any way to simultaneously output the log file continuously (to the screen), or alternatively, make the shell script write to both the log file and stdout at the same time?
我基本上想在 Python 中做这样的事情:
I basically want to do something like this in Python:
cat file 2>&1 | tee -a logfile #"cat file" will be replaced with some script
同样,这将 stderr/stdout 一起传送到 tee,tee 将其同时写入 stdout 和我的日志文件.
Again, this pipes stderr/stdout together to tee, which writes it both to stdout and my logfile.
我知道如何在 Python 中将 stdout 和 stderr 写入日志文件.我被困的地方是如何将这些复制回屏幕:
I know how to write stdout and stderr to a logfile in Python. Where I'm stuck is how to duplicate these back to the screen:
subprocess.Popen("cat file", shell=True, stdout=logfile, stderr=logfile)
当然,我可以做这样的事情,但是有没有办法在没有 tee 和 shell 文件描述符重定向的情况下做到这一点?:
Of course, I could just do something like this, but is there any way to do this without tee and shell file descriptor redirection?:
subprocess.Popen("cat file 2>&1 | tee -a logfile", shell=True)
解决方案
你可以使用管道从程序的stdout中读取数据,并将其写入你想要的所有地方:
You can use a pipe to read the data from the program's stdout and write it to all the places you want:
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 会为你解码
In python 3, the universal_newlines
parameter controls how pipes are used. If False
, pipe reads return bytes
objects and may need to be decoded (e.g., line.decode('utf-8')
) to get a string. If True
, python does the decode for you
在 3.3 版中更改:当 universal_newlines 为 True 时,该类使用编码 locale.getpreferredencoding(False) 而不是 locale.getpreferredencoding().有关此更改的更多信息,请参阅 io.TextIOWrapper 类.
Changed in version 3.3: When universal_newlines is True, the class uses the encoding locale.getpreferredencoding(False) instead of locale.getpreferredencoding(). See the io.TextIOWrapper class for more information on this change.
相关文章