ima*_*hat 38 python subprocess popen
我正在使用Popen调用一个shell脚本,该脚本不断将其stdout和stderr写入日志文件.有没有办法连续同时输出日志文件(到屏幕),或者让shell脚本同时写入日志文件和标准输出?
我基本上想在Python中做这样的事情:
cat file 2>&1 | tee -a logfile #"cat file" will be replaced with some script
Run Code Online (Sandbox Code Playgroud)
再次,这将stderr/stdout连接到tee,将它写入stdout和我的日志文件.
我知道如何在Python中将stdout和stderr写入日志文件.我被困在哪里是如何将这些复制回屏幕:
subprocess.Popen("cat file", shell=True, stdout=logfile, stderr=logfile)
Run Code Online (Sandbox Code Playgroud)
当然我可以做这样的事情,但有没有办法在没有tee和shell文件描述符重定向的情况下做到这一点?:
subprocess.Popen("cat file 2>&1 | tee -a logfile", shell=True)
Run Code Online (Sandbox Code Playgroud)
tde*_*ney 37
您可以使用管道从程序的标准输出中读取数据并将其写入您想要的所有位置:
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()
Run Code Online (Sandbox Code Playgroud)
UPDATE
在python 3中,该universal_newlines参数控制管道的使用方式.如果False,管道读取返回bytes对象,可能需要解码(例如line.decode('utf-8'))以获取字符串.如果True,python为你解码
版本3.3中更改:当universal_newlines为True时,类使用编码locale.getpreferredencoding(False)而不是locale.getpreferredencoding().有关此更改的更多信息,请参阅io.TextIOWrapper类.
jfs*_*jfs 14
要模拟:subprocess.call("command 2>&1 | tee -a logfile", shell=True)不调用tee命令:
#!/usr/bin/env python2
from subprocess import Popen, PIPE, STDOUT
p = Popen("command", stdout=PIPE, stderr=STDOUT, bufsize=1)
with p.stdout, open('logfile', 'ab') as file:
for line in iter(p.stdout.readline, b''):
print line, #NOTE: the comma prevents duplicate newlines (softspace hack)
file.write(line)
p.wait()
Run Code Online (Sandbox Code Playgroud)
要解决可能的缓冲问题(如果输出延迟),请参阅Python中的链接:从subprocess.communicate()读取流输入.
这是Python 3版本:
#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE, STDOUT
with Popen("command", stdout=PIPE, stderr=STDOUT, bufsize=1) as p, \
open('logfile', 'ab') as file:
for line in p.stdout: # b'\n'-separated lines
sys.stdout.buffer.write(line) # pass bytes as is
file.write(line)
Run Code Online (Sandbox Code Playgroud)
逐字节写入终端以用于交互式应用程序
此方法立即将其获取的任何字节写入 stdout,这更接近地模拟 的行为tee,特别是对于交互式应用程序。
主要.py
#!/usr/bin/env python3
import os
import subprocess
import sys
with subprocess.Popen(sys.argv[1:], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc, \
open('logfile.txt', 'bw') as logfile:
while True:
byte = proc.stdout.read(1)
if byte:
sys.stdout.buffer.write(byte)
sys.stdout.flush()
logfile.write(byte)
# logfile.flush()
else:
break
exit_status = proc.returncode
Run Code Online (Sandbox Code Playgroud)
睡眠.py
#!/usr/bin/env python3
import sys
import time
for i in range(10):
print(i)
sys.stdout.flush()
time.sleep(1)
Run Code Online (Sandbox Code Playgroud)
首先我们可以进行非交互式健全性检查:
./main.py ./sleep.py
Run Code Online (Sandbox Code Playgroud)
我们看到它实时计数到标准输出。
接下来,对于交互式测试,您可以运行:
./main.py bash
Run Code Online (Sandbox Code Playgroud)
然后,您键入的字符会在您键入时立即出现在终端上,这对于交互式应用程序非常重要。这是当你运行时会发生的情况:
bash | tee logfile.txt
Run Code Online (Sandbox Code Playgroud)
另外,如果您希望输出立即显示在 ouptut 文件上,那么您还可以添加:
logfile.flush()
Run Code Online (Sandbox Code Playgroud)
但tee不这样做,恐怕会影响性能。您可以使用以下方法轻松测试:
tail -f logfile.txt
Run Code Online (Sandbox Code Playgroud)
相关问题:子进程命令的实时输出
在 Ubuntu 18.04、Python 3.6.7 上测试。
| 归档时间: |
|
| 查看次数: |
41027 次 |
| 最近记录: |