python - 子进程命令的实时输出

我正在使用 python 脚本作为流体动力学代码的驱动程序。当需要运行模拟时,我使用 subprocess.Popen 来运行代码,将 stdoutstderr 的输出收集到一个 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)

最初我通过 teerun_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)

您有两种方法可以做到这一点,通过从 readreadline 函数创建迭代器并执行以下操作:

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 时,readreadline 函数将阻塞,直到分别将一个字符写入管道或将一行写入管道.

https://stackoverflow.com/questions/18421757/

相关文章:

python - Ruby 相当于 virtualenv?

c - 将输出重定向到文件时 printf() 和 system() 的结果顺序错误

linux - 如何指定编辑器来打开 crontab 文件? "export EDITOR=vi"不

c - Linux 中的 PATH_MAX 定义在哪里?

for-loop - 检测 'for'循环中最后一个元素的pythonic方法是什么?

c# - 在 Linux 上开发 C#

python - 查找列表中最常见的元素

python - python中的assertEquals与assertEqual

python - 有没有类似 RStudio for Python 的东西?

linux - 如何在不停止的情况下在 Docker 容器中运行 Nginx?