2009-09-07 9 views
34

出力をTest_Pipe.pyから実行したいのですが、Linux上で次のコードを試しましたが、動作しませんでした。subprocess.Popen()からの出力の取得方法

Test_Pipe.py

import time 
while True : 
    print "Someting ..." 
    time.sleep(.1) 

Caller.py

import subprocess as subp 
import time 

proc = subp.Popen(["python", "Test_Pipe.py"], stdout=subp.PIPE, stdin=subp.PIPE) 

while True : 
    data = proc.stdout.readline() #block/wait 
    print data 
    time.sleep(.1) 

proc.stdout.readline()をブロックしたので、データなしプリントアウト。

+0

重複:http://stackoverflow.com/search?q=%5Bpython%5D+subprocess+output、http://stackoverflow.com/questions/803265/getting-realtime-output-using-subprocess、http: //stackoverflow.com/questions/1277866/python-subprocess-module-looping-over-stdout-of-child-process –

答えて

39

あなたは明らかにsubprocess.communicateを使用できますが、私はあなたがリアルタイムの入出力を探していると思います。

readlineがブロックされていた可能性があります。あなたは次のようにこれを克服するために文字で文字を読むことができます:

import subprocess 
import sys 

process = subprocess.Popen(
    cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE 
) 

while True: 
    out = process.stdout.read(1) 
    if out == '' and process.poll() != None: 
     break 
    if out != '': 
     sys.stdout.write(out) 
     sys.stdout.flush() 
+2

[この場合は 'process.poll()'は必要ありません](http:// stackoverflow.com/a/17701672/4279)。 – jfs

12

常に、このような「リアルタイムでメインプロセスにサブプロセスの出力を取得」などのタスクのためのバッファリングに発生する可能性が多くの問題を回避するために、私はこのようなタスクが必要な場合は、subprocessではなく、Windows上のすべてのプラットフォームにpexpect、Windowsではwexpectを使用することを常にお勧めします。

+0

pexpectへのリンクが更新されました:https://github.com/pexpect/pexpect –

20

ナディアのスニペットは機能しますが、1バイトのバッファで読み込みを呼び出すことは非常に推奨されていません。これを行うには良い方法は、fcntlの

fcntl.fcntl(
    proc.stdout.fileno(), 
    fcntl.F_SETFL, 
    fcntl.fcntl(proc.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK, 
) 

を使用して非ブロッキングし、その後のデータは、彼女はその問題に正解した

while proc.poll() == None: 
    readx = select.select([proc.stdout.fileno()], [], [])[0] 
    if readx: 
     chunk = proc.stdout.read() 
     print chunk 

準備ができているかどうかをテストするために選択し使用して標準出力ファイルディスクリプタを設定することですCaller.pyとTest_Pipe.pyが提供されているように機能するので、あなたが投稿したものと異なる必要があります。

+0

[ブロックバッファリングの問題]のため、問題のコードより早く出力が生成されることはありません。私の答えを参照してください](http://stackoverflow.com/a/17701672/4279)。 – jfs

+0

コードはリアルタイムで出力を生成します。あなたはそれに問題がありましたか? –

+0

コメントのリンクをたどります。 – jfs

7

Test_Pipe.pyバッファサイズが8キロバイトであれば、それは埋めるために分の周りにかかる(子供のバッファがいっぱいになるまでそうCaller.pyprocも出力されないデフォルトでは、その標準出力をバッファリングTest_Pipe.pyのstdoutバッファ)。

出力をバッファなし(テキストストリームの場合はラインバッファ)にするには、-u flagを子Pythonスクリプトに渡すことができます。これは、 『リアルタイム』での線で出力ラインサブプロセスを読み取ることができます:

import sys 
from subprocess import Popen, PIPE 

proc = Popen([sys.executable, "-u", "Test_Pipe.py"], stdout=PIPE, bufsize=1) 
for line in iter(proc.stdout.readline, b''): 
    print line, 
proc.communicate() 

は非Pythonの子プロセスのためのブロック・バッファリングの問題を解決する方法についてPython: read streaming input from subprocess.communicate()のリンクを参照してください。

+1

もう一度1バイトのバッファを使用していますが、これは非常に非効率的です。 –

+4

@DerrickPetzold:間違っています。 'bufsize = 1'は"ラインバッファリング "を意味します。 'bufsize = -1'と同じバッファサイズを使います。実際にコードを実行する(時間のパフォーマンスを比較し、最初のバイトが読み取られるまでの時間を測定する)場合は、両方のコメントが間違っていることがわかったかもしれません。 – jfs

+1

私は画面に直接印刷できるのでまた、popenの結果を保存して、後でエラーコードをチェックするなどしましょう。thumbs up =)私はbufsizeを使って実行し、自分のコードでうまく動作します。 – pelos

関連する問題