web-dev-qa-db-ja.com

何かがファイルに書き込まれているのをライブで見る

pythonプログラムがあり、ゆっくりと出力を生成しています。

それをファイルに取り込みたいのですが、尻尾を付けてライブで観ることもできると思いました。

だから私がやっている1つのターミナルで:

python myprog.py > output.txt

そして別のターミナルで:

tail -f output.txt

しかし、pythonプログラムの実行中、尾が何も表示していないようです。

Ctrl-cを押してpythonスクリプトを殺すと、突然output.txtが充填を開始します。 pythonが実行されている間ではありません。

何が悪いのですか?

25
interstar

また、生成時にパイプされるために、バッファを明示的にフラッシュする必要がある場合もあります。これは、出力が通常はパイプのバッファーがいっぱいになったとき(これは私が生きているキロバイト単位)、およびstdinメッセージが終了したときにのみ出力されるためです。これはおそらく、読み取り/書き込みを節約するためです。これは、すべての印刷の後で、またはループしている場合は、ループ内の最後の印刷の後に行うことができます。

import sys
...
print('Some message')
sys.stdout.flush()
43
Davey

pythonをunbufferedフラグで実行します:

python -u myprog.py > output.txt

その後、出力はリアルタイムで印刷されます。

33
BHC

ライブファイルをテール処理する代わりに、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の答えは明らかに正しい最良の答えです。

19
n8te

用語:このシナリオには、どこにもパイプはありません。 (私はそれを修正するために質問を編集しました)。パイプは別のタイプのファイル(カーネル内のバッファー)です。

これは通常のファイルへの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'

9
Peter Cordes

Tailを使用すると、ほぼ常にログファイル、たとえば(電子メール)メッセージが追跡されます。

これは少し壁から外れているかもしれませんが、print/print()/write()をPythonコードで使用する代わりに、なぜロギングモジュールを使用しないのですか?(PSLから)NBロギングフォーマッターは、従来のログに関連付けられたすべての時間とIDコードを出力しないように構成できます。

出力は(データ)ファイルに移動するように構成でき、バッファリングの遅延やリダイレクトがないため、tailは問題なく即時に機能します。

よろしく

0
d-n