サブプロセスコマンドからのライブ出力 質問する

サブプロセスコマンドからのライブ出力 質問する

私は、流体力学コードのドライバーとして Python スクリプトを使用しています。シミュレーションを実行するときは、subprocess.Popenコードを実行し、出力を--- から収集してstdout---に取り込み、出力情報を印刷 (およびログ ファイルに保存) して、エラーがないか確認します。問題は、コードがどのように進行しているかがまったくわからないことです。コマンド ラインから直接実行すると、どの反復段階であるか、何時か、次のタイム ステップは何かなどの出力が得られます。stderrsubprocess.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)

もともと私は、コピーが直接ログファイルに送信され、ストリームが直接端末に出力されるようにパイプしていましたrun_commandtee、その方法ではエラーを保存できません (私の知る限り)。


これまでの私の一時的な解決策:

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(st log_file = 'log.txt') を実行します。

ベストアンサー1

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、次の操作を実行するという 2 つの方法があります。

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または、ファイルを作成することもできますwriterwriterPopenそして、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、それぞれ 1 文字がパイプに書き込まれるか、または 1 行がパイプに書き込まれるまでブロックされます。

おすすめ記事