2016-06-20 3 views
1

私はstdout.readlineを試して、結果を(つまり、端末に印刷した時点で)multiprocessing.Queueの別の.pyファイルに入れてください。しかし、コール:PythonはPopenを継続的に読み取っています(Windows)

res = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1) 
with res.stdout: 
    for line in iter(res.stdout.readline, b''): 
     print line 
res.wait() 

はブロックされます、結果は(終了コードが返されていない場合または全くない)プロセスが完了した後に印刷されます。

私はこれに対する答えを閲覧し、bufsize = 1、読み込みを処理するスレッドを生成する、filedescriptorsなどを使用してみましたが、うまくいかないようです。私はモジュールpexpectを使用しなければならないかもしれませんが、私はまだそれがどのように動作するのか分かりません。

私はまた、キューにデータを配置するには、しかしout.readlineをブロックするように思わ以来、結果は同じになります

def enqueue_output(self, out, queue): 
    for line in iter(out.readline, b''): 
     queue.put([line]) 
    out.close() 

を試してみました。

要約:印刷時にサブプロセス出力を私に利用可能にするにはどうすればよいですか?しかし、これらは私に返され、一度に1〜10行のチャンクを印刷し、プロセスが完了すると、

関連..だけでなく改行で区切ら:

Python subprocess readlines() hangs

Python: read streaming input from subprocess.communicate()

Non-blocking read on a subprocess.PIPE in python

+0

バッファリングを無効にしたり、Pythonの "-u"や "-i"オプションなどの対話モードを使用するには、プログラムにコマンドラインオプションがあるかどうかを調べる必要があります。さもなければ、パイプであることがわかると、 'stdout'にバッファリングする可能性が高くなります。出力は、バッファがいっぱいになったとき、またはプログラムがバッファを手動でフラッシュするとき、または出力が終了したときにのみパイプに書き込まれます。パイプのもう一方の端にあるPythonは、この動作を制御しません。 – eryksun

+0

あなたはpexpectに言及し、質問に "pty"というタグを付けましたが、Windowsには端末と擬似端末がありません。 pexpectに最も近いのはwinpexpectですが、それはパイプを使用しているので、バッファリングの問題は解決しません。これをWindowsで正しく処理するにはコンソールAPIが必要です。ウィンドウレスコンソールにヘルパープログラムを添付して、プログラムの出力を読み込んで入力に書き込むことがあります。私はWindows用にこれを実装するPythonモジュールを見たことがありません。 – eryksun

+0

@eryksun ptyタグを削除しました。私はこの問題が私が呼んでいるプロセスにあるのではないかと恐れていました。責任ある開発者にそれを求めなければなりません。 Windowsを実行し、サブプロセスとコマンドライン機能を使用するときにバッファリングに関するいくつかの問題があるようです。 – enrm

答えて

1

@eryksunで説明されているように、コメントによって確認されたように、バッファリングの原因はCアプリケーションによるprintfの使用です。

デフォルトでは、printfは出力をバッファリングしますが、出力が改行でフラッシュされるか、または出力が端末に向けられたときに読み取りが発生すると、が出力されます。出力がファイルまたはパイプに送られると、実際の出力はバッファがいっぱいになったときにのみ発生します。

幸いにもWindowsでは、低レベルのバッファリング(*)がありません。つまり、プログラムの始めのほうにsetvbuf(stdout, NULL, _IONBF, 0);を呼び出すだけで十分です。残念ながら、バッファリングは一切必要ありません(_IONBF).Windowsでのバッファリングはフルバッファリングとして実装されているためです。

(*)UnixまたはLinuxシステムでは、基本となるシステムコールで独自のバッファリングを追加できます。つまり、ローレベルのwrite(1, buf, strlen(buf));を使用するプログラムは、Windowsではバッファリングされませんが、標準出力がパイプまたはファイルに接続されている場合はLinuxでバッファされます。

+0

関連情報を提供するためのアップ・ボーティング。最初の質問に答えるには:ストリームが閉じられるまでバッファを取得する方法はありませんか? – enrm

+0

より正確には、ストリームが閉じられるまで、時々フルバッファを取得します。しかし、呼び出されたプログラムを変更することなく、私はそのバッファリングを避ける方法を想像することはできません。 –

+0

Linuxやその他のUnix OS上のパイプの低レベルバッファリングの参考資料はありますか?パイプ自体にはバッファがあり、 'write'がブロックまたは失敗する前にその容量を決定しますが、片方の' write'はもう片方の 'read'のためにすぐに利用可能でなければなりません。 Windows I/Oでは、一般的なファイルアクセスはシステムキャッシュを使用するので、データがすぐに書き込まれるようにするにはフラグFILE_FLAG_WRITE_THROUGHを使用してファイルを開く必要があります(ただし、デバイスによっては、 ;しかし、パイプの場合、これはネットワーク経由でアクセスされるパイプの場合にのみ重要です。 – eryksun

関連する問題