我正在寻找一个Python解决方案,允许我将命令的输出保存到文件中,同时不隐藏它在控制台上的显示。
FYI:我在问关于Unix命令行实用程序tee(而不是Python intertools模块中同名的函数)。
细节:
- Python解决方案(不调用tee,在Windows下不可用) - 我不需要为所调用的进程提供任何输入 - 我无法控制所调用程序。我只知道它会向stdout和stderr输出一些内容,并返回退出代码。 - 在调用外部程序(subprocess)时工作 - 对于stderr和stdout都能正常工作 - 能够区分stdout和stderr,因为我可能只想将其中一个显示在控制台上,或者我可以尝试使用不同的颜色输出stderr - 这意味着
参考资料:
这里是我找到的一些不完整的解决方案:
预期输出应该按行排序。请注意,修改Popen以仅使用一个PIPE是不允许的,因为在实际情况下,我将希望对stderr和stdout执行不同的操作。
即使在第二种情况下,我也无法获得类似实时的输出,事实上,所有结果都是在进程完成后接收到的。默认情况下,Popen不应使用缓冲区(bufsize=0)。
FYI:我在问关于Unix命令行实用程序tee(而不是Python intertools模块中同名的函数)。
细节:
- Python解决方案(不调用tee,在Windows下不可用) - 我不需要为所调用的进程提供任何输入 - 我无法控制所调用程序。我只知道它会向stdout和stderr输出一些内容,并返回退出代码。 - 在调用外部程序(subprocess)时工作 - 对于stderr和stdout都能正常工作 - 能够区分stdout和stderr,因为我可能只想将其中一个显示在控制台上,或者我可以尝试使用不同的颜色输出stderr - 这意味着
stderr = subprocess.STDOUT
将不起作用。
- 实时输出(渐进式) - 进程可能运行很长时间,我不能等待它完成。
- Python 3兼容代码(重要)参考资料:
这里是我找到的一些不完整的解决方案:
- http://devlishgenius.blogspot.com/2008/10/logging-in-real-time-in-python.html(仅在Unix系统上mkfifo有效)
- http://blog.kagesenshi.org/2008/02/teeing-python-subprocesspopen-output.html(完全无效)
Diagram http://blog.i18n.ro/wp-content/uploads/2010/06/Drawing_tee_py.png
当前代码(第二次尝试)
#!/usr/bin/python
from __future__ import print_function
import sys, os, time, subprocess, io, threading
cmd = "python -E test_output.py"
from threading import Thread
class StreamThread ( Thread ):
def __init__(self, buffer):
Thread.__init__(self)
self.buffer = buffer
def run ( self ):
while 1:
line = self.buffer.readline()
print(line,end="")
sys.stdout.flush()
if line == '':
break
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdoutThread = StreamThread(io.TextIOWrapper(proc.stdout))
stderrThread = StreamThread(io.TextIOWrapper(proc.stderr))
stdoutThread.start()
stderrThread.start()
proc.communicate()
stdoutThread.join()
stderrThread.join()
print("--done--")
#### test_output.py ####
#!/usr/bin/python
from __future__ import print_function
import sys, os, time
for i in range(0, 10):
if i%2:
print("stderr %s" % i, file=sys.stderr)
else:
print("stdout %s" % i, file=sys.stdout)
time.sleep(0.1)
stderr 1
stdout 0
stderr 3
stdout 2
stderr 5
stdout 4
stderr 7
stdout 6
stderr 9
stdout 8
--done--
预期输出应该按行排序。请注意,修改Popen以仅使用一个PIPE是不允许的,因为在实际情况下,我将希望对stderr和stdout执行不同的操作。
即使在第二种情况下,我也无法获得类似实时的输出,事实上,所有结果都是在进程完成后接收到的。默认情况下,Popen不应使用缓冲区(bufsize=0)。