我正在使用 python 脚本作为流体动力学代码的驱动程序。当需要运行模拟时,我使用 subprocess.Popen
来运行代码,将 stdout
和 stderr
的输出收集到一个 subprocess.PIPE
--- 然后我可以打印(并保存到日志文件)输出信息,并检查是否有任何错误。问题是,我不知道代码是如何进行的。如果我直接从命令行运行它,它会输出关于它的迭代时间、时间、下一个时间步长等信息。
有没有办法既存储输出(用于日志记录和错误检查)又生成实时流输出?
我的代码的相关部分:
ret_val = subprocess.Popen( run_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True )
output, errors = ret_val.communicate()
log_file.write(output)
print output
if( ret_val.returncode ):
print "RUN failed\n\n%s\n\n" % (errors)
success = False
if( errors ): log_file.write("\n\n%s\n\n" % errors)
最初我通过 tee
将 run_command
传递给管道,以便副本直接进入日志文件,并且流仍然直接输出到终端——但是方式我不能存储任何错误(据我所知)。
到目前为止我的临时解决方案:
ret_val = subprocess.Popen( run_command, stdout=log_file, stderr=subprocess.PIPE, shell=True )
while not ret_val.poll():
log_file.flush()
然后,在另一个终端中,运行 tail -f log.txt
(s.t. log_file = 'log.txt'
)。
最佳答案
Python 3 的 TLDR:
import subprocess
import sys
with open("test.log", "wb") as f:
process = subprocess.Popen(your_command, stdout=subprocess.PIPE)
for c in iter(lambda: process.stdout.read(1), b""):
sys.stdout.buffer.write(c)
f.buffer.write(c)
您有两种方法可以做到这一点,通过从 read
或 readline
函数创建迭代器并执行以下操作:
import subprocess
import sys
# replace "w" with "wb" for Python 3
with open("test.log", "w") as f:
process = subprocess.Popen(your_command, stdout=subprocess.PIPE)
# replace "" with b'' for Python 3
for c in iter(lambda: process.stdout.read(1), ""):
sys.stdout.write(c)
f.write(c)
或
import subprocess
import sys
# replace "w" with "wb" for Python 3
with open("test.log", "w") as f:
process = subprocess.Popen(your_command, stdout=subprocess.PIPE)
# replace "" with b"" for Python 3
for line in iter(process.stdout.readline, ""):
sys.stdout.write(line)
f.write(line)
或者您可以创建一个 reader
和一个 writer
文件。将 writer
传递给 Popen
并从 reader
import io
import time
import subprocess
import sys
filename = "test.log"
with io.open(filename, "wb") as writer, io.open(filename, "rb", 1) as reader:
process = subprocess.Popen(command, stdout=writer)
while process.poll() is None:
sys.stdout.write(reader.read())
time.sleep(0.5)
# Read the remaining
sys.stdout.write(reader.read())
这样您将在 test.log
以及标准输出中写入数据。
文件方法的唯一优点是您的代码不会阻塞。因此,您可以在此期间做任何您想做的事情,并以非阻塞方式随时从 reader
读取。当您使用 PIPE
时,read
和 readline
函数将阻塞,直到分别将一个字符写入管道或将一行写入管道.
https://stackoverflow.com/questions/18421757/