subprocess.Popenのstdoutとstderrをリアルタイムに取得する
pythonの subprocess.Popen
で子プロセスのstdoutとstderrの内容を加工した上で、親のstdout、stderrにそれぞれリアルタイムに、且つ順番通りに出力したいです。
例えば、以下の hoge.sh
を 実行例
のように実行したいです。
hoge.sh
echo yes1
echo no1 >&2
echo yes21
echo yes22
echo no2 >&2
fuga.py:
import subprocess as sp
p = sp.Popen(['bash', 'hoge.sh'], stdout=sp.PIPE, stderr=sp.PIPE, ...)
~~ p.stdoutは先頭に"out:"を、p.stderrは"err:"をつけて出力 ~~
p.wait()
実行例:
$ python fuga.py ※加工されたstdout stderr が順番通り出力される
out: yes1
err: no1
out: yes21
out: yes22
err: no2
$ python fuga.py > /dev/null ※加工されたstderr のみ出力される
err: no1
err: no2
ネットで見つけた以下のコードが今の所もっとも目的に近いのですが、こちらのコードではstdoutとstderrの順番が保証されません。
#!/usr/bin/python3
import subprocess
import sys
from subprocess import PIPE
from threading import Thread
def read_stream(in_file, out_file):
for line in in_file:
print(line.strip(), file=out_file, flush=True)
p = subprocess.Popen("./test_stream.py", stdin=sys.stdin, stdout=PIPE, stderr=PIPE, universal_newlines=True)
Thread(target=read_stream, args=(p.stdout, sys.stdout)).start()
Thread(target=read_stream, args=(p.stderr, sys.stderr)).start()
出力結果: (stdoutとstderrの順番が入れ替わることがある)
out: yes1
err: no1
out: yes21
err: no2
out: yes22
お力添えのほど何卒よろしくお願いします。