2

強調するために、問題は非ブロック読み取りではなくリアルタイム読み取りです。subprocess.Popen.stdout - reading stdout in real-time (again)など、以前に尋ねられました。しかし、満足のいく解決策は提案されていません。

例として、次のコードは Python シェルをシミュレートしようとします。

import subprocess

p = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

while True:
    line = input('>>> ')
    p.stdin.write(line.encode())
    print('>>> ', p.stdout.read().decode())

ただし、から読み取るとブロックされp.stdoutます。いろいろと調べてみると、以下の2つの解決策が見つかりました。

  1. を使用fctrlしてO_NONBLOCK
  2. を使用threadしてqueue

1 番目の解決策は機能し、Linux でのみ機能する可能性がありますが、2 番目の解決策はブロック読み取りを非ブロック読み取りに変えるだけです。つまり、サブプロセスのリアルタイム出力を取得できません。たとえば、「 」と入力すると、 2 番目のソリューションを使用してprint("hello")も何も得られません。p.stdout

おそらく、誰かが提案するでしょうp.communite残念ながら、ここで説明されているように標準入力を閉じるため、この場合には適していません。

それで、Windowsの解決策はありますか?

編集済み:-uをオンにしてp.stdout.readに置き換えてもp.stdout.readline、問題は依然として存在します。

import subprocess

p = subprocess.Popen(['python', '-u'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

while True:
    line = input('>>> ')
    p.stdin.write(line.encode())
    p.stdin.flush()
    print('>>> ', p.stdout.readline().decode())

解決策:以下は、JF Sebastian の回答とコメントに基づく最終的なコードです。

from subprocess import Popen, PIPE, STDOUT

with Popen(
        ['python', '-i', '-q'],
        stdin=PIPE, stdout=PIPE, stderr=STDOUT,
        bufsize=0
    ) as process:
    while True:
        line = input('>>> ')
        if not line:
            break
        process.stdin.write((line+'\n').encode())
        print(process.stdout.readline().decode(), end='')

コマンドが出力をトリガーしない場合、プログラムがハングすることに注意してください。

4

1 に答える 1

0

サブプロセスをインタラクティブに使用する完全な作業例を次に示します。

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

with Popen([sys.executable, '-i'], stdin=PIPE, stdout=PIPE, stderr=DEVNULL,
           universal_newlines=True) as process:
    for i in range(10):
        print("{}**2".format(i), file=process.stdin, flush=True)
        square = process.stdout.readline()
        print(square, end='')

別の例: how to run [sys.executable, '-u', 'test.py']interactively .

于 2016-04-28T02:24:34.807 に答える