75

1st.pyREPL (read-eval-print-loop) を作成するという名前のスクリプトがあります。

print "Something to print"
while True:
    r = raw_input()
    if r == 'n':
        print "exiting"
        break
    else:
        print "continuing"

1st.py次に、次のコードで起動しました。

p = subprocess.Popen(["python","1st.py"], stdin=PIPE, stdout=PIPE)

そして、これを試しました:

print p.communicate()[0]

失敗し、次のトレースバックが提供されました。

Traceback (most recent call last):
  File "1st.py", line 3, in <module>
    r = raw_input()
EOFError: EOF when reading a line

ここで何が起こっているのか説明してもらえますか? を使用するp.stdout.read()と、永久にハングします。

4

3 に答える 3

67

.communicate()入力を書き込み(この場合は入力がないため、サブプロセスのstdinを閉じて、サブプロセスに入力がないことを示します)、すべての出力を読み取り、サブプロセスが終了するのを待ちます。

子プロセスで例外 EOFError が発生しますraw_input()(データを期待していましたが、EOF を取得しました (データなし))。

p.stdout.read()子がデッドロックの原因となる入力 ( ) を待機すると同時に、子からすべての出力を読み取ろうとするため、永久にハングします。raw_input()

デッドロックを回避するには、非同期で読み取り/書き込みを行うか (たとえば、スレッドまたは選択を使用して)、または読み取り/書き込みのタイミングと量を正確に把握する必要があります

from subprocess import PIPE, Popen

p = Popen(["python", "-u", "1st.py"], stdin=PIPE, stdout=PIPE, bufsize=1)
print p.stdout.readline(), # read the first line
for i in range(10): # repeat several times to show that it works
    print >>p.stdin, i # write input
    p.stdin.flush() # not necessary in this case
    print p.stdout.readline(), # read output

print p.communicate("n\n")[0], # signal the child to exit,
                               # read the rest of the output, 
                               # wait for the child to exit

注: 読み取り/書き込みが同期していない場合、非常に壊れやすいコードです。デッドロックします。

ブロック バッファリングの問題に注意してください(ここでは、「-u」フラグを使用して stdin のバッファリングを無効にすることで解決されます)

bufsize=1親側でパイプをラインバッファリングします。

于 2013-05-27T09:40:37.363 に答える
25

通信(input="")を使用しないでください。入力をプロセスに書き込み、標準入力を閉じてから、すべての出力を読み取ります。

次のようにします。

p=subprocess.Popen(["python","1st.py"],stdin=PIPE,stdout=PIPE)

# get output from process "Something to print"
one_line_output = p.stdout.readline()

# write 'a line\n' to the process
p.stdin.write('a line\n')

# get output from process "not time to break"
one_line_output = p.stdout.readline() 

# write "n\n" to that process for if r=='n':
p.stdin.write('n\n') 

# read the last output from the process  "Exiting"
one_line_output = p.stdout.readline()

エラーを取り除くために行うこと:

all_the_process_will_tell_you = p.communicate('all you will ever say to this process\nn\n')[0]

しかし、communication はstdoutandstdinと を閉じるので、communicationstderrを呼び出した後は読み書きできません。

于 2013-05-27T09:17:38.407 に答える
0

コードの 2 番目のビットは、コードの最初のビットを、入力と出力がパイプ処理されたサブプロセスとして開始します。次に、入力を閉じて、出力を読み取ろうとします。

コードの最初のビットは標準入力から読み取ろうとしますが、それを開始したプロセスが標準入力を閉じたため、すぐにファイルの終わりに到達し、Python が例外に変換します。

于 2013-05-27T07:31:21.693 に答える