1. ホーム
  2. python

[解決済み] サブプロセスによるリアルタイム出力の取得

2022-04-27 23:38:55

質問

コマンドライン・プログラム(svnadmin verify)のラッパースクリプトを書いて、操作の進捗状況をうまく表示しようとしています。 そのためには、ラップされたプログラムから出力される各行を、出力されると同時に見ることができる必要があります。

を使ってプログラムを実行すればいいんだと思ったんだ。 subprocess.Popen を使用します。 stdout=PIPE そして、各行を読み込んで、それに応じて行動します。 しかし、次のコードを実行すると、出力はどこかでバッファリングされているようで、1行目から332行目、そして333行目から439行目(出力の最終行)という2つのチャンクに分かれて表示されるようになりました。

from subprocess import Popen, PIPE, STDOUT

p = Popen('svnadmin verify /var/svn/repos/config', stdout = PIPE, 
        stderr = STDOUT, shell = True)
for line in p.stdout:
    print line.replace('\n', '')

サブプロセスのドキュメントを少し見た後、私は bufsize パラメータを Popen ということで、bufsizeを1(行ごとにバッファする)と0(バッファしない)に設定してみましたが、どちらの値でも行の配信方法は変わらないようです。

この時点で藁にもすがる思いで、次のような出力ループを書きました。

while True:
    try:
        print p.stdout.next().replace('\n', '')
    except StopIteration:
        break

が、同じ結果になりました。

サブプロセスを使って実行されたプログラムの出力を「リアルタイム」に取得することは可能でしょうか? Pythonに前方互換性のある他のオプションはありますか( exec* )?

解決方法は?

これを試したのですが、なぜかコード中に

for line in p.stdout:
  ...

は積極的にバッファリングし、バリアント

while True:
  line = p.stdout.readline()
  if not line: break
  ...

を実行しない。どうやらこれは既知のバグのようです。 http://bugs.python.org/issue3907 (この問題は2018年8月29日現在、"Closed"となっています)