13

わかりましたので、そのようなスレッドを何十も見てきましたが、完全な答えが得られるものはなく、これまでに試したすべての敵がうまくいきませんでした。

1) 一定のデータを常に出力してフラッシュするスクリプト:

import time
import sys

if __name__ == '__main__':
    for i in range(5):
        print i,
        sys.stdout.flush()
        time.sleep(1)

2) Popen で最初のスクリプトを呼び出し、数値を 1 つずつ出力する必要があるのに、何らかの理由で数値を出力せず、それらを一度にまとめて出力するスクリプト:

import sys
import subprocess

if __name__ == '__main__':
    process = subprocess.Popen(['python', 'flush.py'], stdout = subprocess.PIPE )
    for line in iter(process.stdout.readline, ''):
        print line,
        sys.stdout.flush()

最初に少し混乱しているのは、最初のスクリプトで、フラッシュを削除すると、出力が 1 行にまとめて O_O に返されることです... time.sleep が原因であると確信していますが、それでも標準出力は常に値0、1、2、3、4を返しますが、すべて一緒ではありません。もちろん、フラッシュはそれを解決しますが、少なくとも私にとっては奇妙です...

主な問題: 2 番目のスクリプトは番号を 1 つずつ返さず、一度にすべてを 1 つの出力で返します..... 必要なのは、数字が 1 つずつ飛び出すのを確認することです...

Popenがパイプを閉じるのを待つEOFを返さないことをどこかで読みました。それが最後まで実行される理由です.....

それで、私は何をするか、次に試しますか? 前もって感謝します。

4

1 に答える 1

13

@Warren Weckesser のコメントにあるように、あなたの問題はバッファリングの問題とは無関係です。

.readline()親プロセスでは、改行を読み取るかEOFに達するまで戻りません。子プロセスは改行をまったく出力しないため、子プロセスが終了するまで親プロセスは何も出力しません。

print i,最小限の修正は、子スクリプトの最後にあるカンマを削除することです。

これも機能します:

#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE

p = Popen([sys.executable or 'python',
           '-u', # unbuffer stdout (or make it line-buffered on Python 3)
           '-c',
           """
import time

for i in range(5):
    print(i) # <-- no comma i.e., each number is on its own line
    time.sleep(1)
"""], stdout=PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
    print(int(line)**2)

例:

 $ python parent.py
 0
 1
 4
 9
 16

数値は、子プロセスが終了するのを待たずに毎秒表示されます。

子スクリプトを変更したくない場合readline()は、改行文字の代わりに空白で停止するものを使用する必要があります。

#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE

p = Popen(['python2', 'child.py'], stdout=PIPE, bufsize=0)
for token in generate_tokens(p.stdout):
    print(int(token))

wheregenerate_tokens()は空白で区切られたトークンを生成します:

def generate_tokens(pipe):
    buf = []
    while True:
        b = pipe.read(1) # read one byte
        if not b: # EOF
            pipe.close()
            if buf:
                yield b''.join(buf)
            return
        elif not b.isspace(): # grow token
            buf.append(b)
        elif buf: # full token read
            yield b''.join(buf)
            buf = []

また、子によって出力されるとすぐに整数も出力します。

于 2013-12-13T21:16:49.587 に答える