pythonプログラムがあり、ゆっくりと出力を生成しています。
それをファイルに取り込みたいのですが、尻尾を付けてライブで観ることもできると思いました。
だから私がやっている1つのターミナルで:
python myprog.py > output.txt
そして別のターミナルで:
tail -f output.txt
しかし、pythonプログラムの実行中、尾が何も表示していないようです。
Ctrl-cを押してpythonスクリプトを殺すと、突然output.txt
が充填を開始します。 pythonが実行されている間ではありません。
何が悪いのですか?
また、生成時にパイプされるために、バッファを明示的にフラッシュする必要がある場合もあります。これは、出力が通常はパイプのバッファーがいっぱいになったとき(これは私が生きているキロバイト単位)、およびstdinメッセージが終了したときにのみ出力されるためです。これはおそらく、読み取り/書き込みを節約するためです。これは、すべての印刷の後で、またはループしている場合は、ループ内の最後の印刷の後に行うことができます。
import sys
...
print('Some message')
sys.stdout.flush()
pythonをunbufferedフラグで実行します:
python -u myprog.py > output.txt
その後、出力はリアルタイムで印刷されます。
ライブファイルをテール処理する代わりに、tee
を使用してください。あなたがやろうとしていることを正確に行うために作られました。
man tee から:
tee(1)-Linuxのマニュアルページ
Nametee-標準入力から読み取り、標準出力とファイルに書き込みます
概要
_tee [OPTION]... [FILE]...
_説明
標準入力を各FILEにコピーし、標準出力にもコピーします。
_-a, --append append to the given FILEs, do not overwrite -i, --ignore-interrupts ignore interrupt signals --help display this help and exit --version output version information and exit
_FILEが-の場合、標準出力に再度コピーします。
したがって、あなたの場合は次のように実行します:
_python myprog.py | tee output.txt
_
編集:他の人が指摘したように、この回答は、Daveyの承認済み回答に記載されているようにpythonプログラムでsys.stdout.flush()
が使用されていない限り、OPが最初に持っていたのと同じ問題にぶつかります。この回答を投稿する前に行ったテストは、OPのユースケースを正確に反映していませんでした。
tee
は、最適ではありませんが、ファイルへの書き込みと同時に出力を表示する方法として代替として使用できますが、Daveyの答えは明らかに正しい最良の答えです。
用語:このシナリオには、どこにもパイプはありません。 (私はそれを修正するために質問を編集しました)。パイプは別のタイプのファイル(カーネル内のバッファー)です。
これは通常のファイルへのredirectです。
C stdioおよびPythonでは、TTYに接続されている場合、デフォルトでstdoutがラインバッファリングされます。それ以外の場合は、フルバッファリングされます。行バッファリングは、バッファが改行の後にフラッシュされることを意味します。フルバッファリングとは、フルになると、フラッシュされてOSから見えるようになる(つまり、write()
システムコールで)だけです。
最終的には、一度に4kiBのチャンクで出力が表示されます。 (デフォルトのバッファーサイズはわかりません。)これは一般に効率がよく、実際のディスクへの書き込みが少なくなります。ただし、出力はフラッシュされるまで書き込みプロセスのメモリ内に隠されるため、インタラクティブな監視には適していません。
Stack Overflowには Disable output buffering Python Q&Aがあり、Pythonのstdoutにバッファーなし(またはラインバッファー付き)の出力を取得する多くの方法がリストされています。質問自体答えを要約します。
オプションには、python -u
の実行(または#!/usr/bin/python -u
をスクリプトの先頭に置く)、またはそのプログラムのPYTHONUNBUFFERED
環境変数の使用が含まれます。または、@ Daveyの回答が示唆するように、一部またはすべてのprint
関数の後に明示的にフラッシュします。
他のいくつかのプログラムには、同様のオプションがあります。 GNU grepには--line-buffered
があり、GNU sed
には-u
/--unbuffered
があります。 -このようなケース、または例えばpythonプログラムの出力をパイプする。例:./slowly-output-stuff | grep --line-buffered 'foo.*bar'
。
Tailを使用すると、ほぼ常にログファイル、たとえば(電子メール)メッセージが追跡されます。
これは少し壁から外れているかもしれませんが、print
/print()
/write()
をPythonコードで使用する代わりに、なぜロギングモジュールを使用しないのですか?(PSLから)NBロギングフォーマッターは、従来のログに関連付けられたすべての時間とIDコードを出力しないように構成できます。
出力は(データ)ファイルに移動するように構成でき、バッファリングの遅延やリダイレクトがないため、tailは問題なく即時に機能します。
よろしく