2

Pythonからシェルコマンドを実行し、subprocess.Popenでその出力を受け取りたいです。問題は、プロセスを閉じてCtrl-Cを送信すると、出力が得られないことです。私は何が間違っているのですか?コード:

>>> import subprocess
>>> sub = subprocess.Popen(["xinput", "test", "8"], stdout=subprocess.PIPE) #receive mouse events
>>> output = sub.communicate()[0].read()
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/subprocess.py", line 693, in communicate
    stdout = self.stdout.read()
KeyboardInterrupt
>>> output
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'output' is not defined

Jettによるこの投稿に触発されました:

Pythonのxinputテストからstdoutを読み取る

4

2 に答える 2

4

ここでの問題は、KeyboardInterruptへのコール中に が送信されることcommunicateです。その結果、communicate決して返されないため、出力が変数に格納されることはなく、使用しようとするoutputと が取得されます。NameError1 つの回避策は次のとおりです。

 import subprocess
 sub = subprocess.Popen(["xinput", "test", "8"], stdout=subprocess.PIPE)
 lines = [] #Need someplace to store the data as it comes
 try:
    for line in sub.stdout: #read one line from standard out, store it in lines
        lines.append(line)
 except KeyboardInterrupt:  #keyboardInterrupt happened.  Stop process
    sub.terminate()
 finally:                   #Join our lines into a single buffer (like `communicate`)
    output = ''.join(lines)
    del lines               #clean `lines` out of our namespace (just because). 
于 2012-09-14T12:24:43.563 に答える
2

@pythonm はすでにNameError.

さらに、Popen.communicate()概念的に間違った出力を使用しています。文字列の 2 タプルを返します: (stdout, stderr). 2 つのファイルのようなオブジェクトは返されません。そのため、返されたsub.communicate()[0].read()場合は失敗します。communicate()

サブプロセスが戻るまで、communicate()その stdout と stderr のすべてを集約します (コンストラクターに提供stdout=subprocess.PIPEしたことを考慮して)。stderr=subprocess.PIPEサブプロセスが終了した後でのみ、サブプロセスcommunicate()の実行中に収集されたものにアクセスできます。

サブプロセスの出力をリアルタイムで監視したい場合、それcommunicate()は間違った方法です。サブプロセスを実行し、(たとえばループ内で) 監視し、そのサブプロセスPopen.stdoutPopen.stderr属性 (ファイルのようなオブジェクト) を操作します。@mgilsonの答えは、それを行う方法の1つを示しています:)

于 2012-09-14T12:24:58.320 に答える