1

外部システム コマンドでユーザー入力が必要になる場合があるスクリプトを作成しています。私はそれを適切に処理することができません。os.popen4 と subprocess モジュールを使用してみましたが、目的の動作を実現できませんでした。

以下の例は、「cp」コマンドを使用してこの問題を示しています。(「cp」コマンドは、この問題を示すために使用されます。シナリオによっては、同様にユーザーの応答を求める可能性のある別の exe を呼び出しています)。この例では、ディスク上に 2 つのファイルが存在し、ユーザーが file1 を file2 にコピーしようとすると、conformer メッセージが表示されます。

proc = subprocess.Popen("cp -i a.txt b.txt", shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,)
stdout_val, stderr_val = proc.communicate()
print stdout_val

b.txt?

proc.communicate("y")

この例では、stdout/stderr のみを読み取って出力すると、後でユーザーの入力に基づいて「y」または「n」を書き込もうとすると、チャネルが閉じているというエラーが発生します。

最初にstdoutを出力してから、ユーザー入力を取り、後でstdinを書き込む必要があるように、Pythonでこの動作を達成するのを手伝ってくれる人がいますか?

python の subprocess.PIPE での非ブロッキング読み取りから別の解決策 (スレッド化) を見つけましたが、それが役立つかどうかはわかりません。しかし、それはcpコマンドからの質問を印刷しているようです.コードを変更しましたが、スレッドコードに書き込む方法がわかりません.

import sys
from subprocess import PIPE, Popen
from threading import Thread
try:
    from Queue import Queue, Empty
except ImportError:
    from queue import Queue, Empty

ON_POSIX = 'posix' in sys.builtin_module_names

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

 p = Popen(['cp', '-i', 'a.txt', 'b.txt'],stdin=PIPE, stdout=PIPE, bufsize=1, close_fds=ON_POSIX)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.start()

try:
    line = q.get_nowait()
except Empty:
    print('no output yet')
else:
   pass
4

2 に答える 2

1

Popen.communicateサブプロセスを完了するまで実行するため、複数回呼び出すことはできません。stdinおよびstdout属性を直接使用することもできますが、プロセスがブロック バッファリングを使用するか、バッファがいっぱいになるとデッドロックする可能性があるため危険です。

stdout_val = proc.stdout.readline()
print stdout_val
proc.stdin.write('y\n')

デッドロックのリスクがあり、プロセスがブロック バッファリングを使用している場合はこれが機能しない可能性があるため、代わりにpexpectパッケージの使用を検討することをお勧めします。

于 2012-07-23T13:15:21.657 に答える
0

この質問に対する技術的な答えはありません。単なる解決策です。プロセスが入力を待つ方法と関係があり、プロセスと通信すると、プロセスを閉じるには None 入力で十分です。

あなたのcp例では、あなたができることは、リターンコードをすぐにチェックすることですproc.poll(). 戻り値が の場合、None入力を待機しようとしていると考えられ、ユーザーに質問することができます。その後、 を介してプロセスに応答を渡すことができますproc.communicate(response)。次に、値を渡し、プロセスを続行します。

communicateおそらく、他の誰かが、None 値を持つイニシャルがプロセスを終了するより技術的な理由でチャイムを鳴らすことができます。

于 2012-07-23T05:32:22.160 に答える