4

現在、私はこのようなものを持っています:

self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE)
out, err = self.process.communicate()

実行しているコマンドは出力をストリーミングします。続行する前にプロセスをブロックする必要があります。

ストリーミング出力をキャプチャし、stdoutを介してストリーミング出力を印刷できるようにするにはどうすればよいですか?を設定stdout=subprocess.PIPEすると、出力をキャプチャできますが、出力が出力されません。を省略するstdout=subprocess.PIPEと、出力は出力されますが、communicate()が返されNoneます。

プロセスが終了/完了するまでブロッキングを提供し、ここで説明したバッファーの問題とパイプのデッドロックの問題を回避しながら、私が求めていることを実行するソリューションはありますか?

ありがとう!

4

2 に答える 2

5

私はいくつかの解決策を考えることができます。

#1:ソースにアクセスして、コードcommunicateを取得し、コピーして貼り付け、各行が入ってくるときに印刷するコードを追加し、バッファリングすることができます。(たとえば、親がデッドロックしているために自分stdoutでブロックできる場合は、threading.Queue代わりにまたは何かを使用できます。)これは明らかに少しハッキーですが、非常に簡単で安全です。

しかし、実際にcommunicateは、完全に一般的である必要があり、そうでない場合を処理する必要があるため、複雑です。ここで必要なのは、問題にスレッドを投げるという中心的なトリックです。read必要なのは、呼び出し間で速度を低下させたりブロックしたりしない専用のリーダースレッドだけです。

このようなもの:

self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE)
lines = []
def reader():
    for line in self.process.stdout:
        lines.append(line)
        sys.stdout.write(line)
t = threading.Thread(target=reader)
t.start()
self.process.wait()
t.join()

readerスレッドでエラー処理が必要になる場合があります。そして、私はあなたがreadlineここで安全に使用できるかどうか100%確信していません。しかし、これはうまくいくか、近いでしょう。

#2:または、ファイルオブジェクトを取得し、誰かがそこから移動するたびにstdout/にティーするラッパークラスを作成できます。次に、automagicを使用する代わりに、パイプを手動で作成し、ラップされたパイプを渡します。これには、#1とまったく同じ問題があります(問題がないか、ブロックできる場合は、または何かを使用する必要があることを意味します)。stderrreadPIPEQueuesys.stdout.write

このようなもの:

class TeeReader(object):
    def __init__(self, input_file, tee_file):
        self.input_file = input_file
        self.tee_file = tee_file
    def read(self, size=-1):
        ret = self.input_file.read(size)
        if ret:
            self.tee_file.write(ret)
        return ret

つまり、ファイルオブジェクト(またはそのように機能するもの)をラップし、ファイルオブジェクトのように機能します。(を使用する場合PIPEprocess.stdoutはUnixでは実際のファイルオブジェクトですが、Windowsでのように機能する場合があります。)委任する必要のある他のメソッドはinput_file、余分な折り返しなしで直接委任できます。これを試して、どのメソッドcommunicateAttributeException検索され、それらを明示的にコーディングするかを確認するか、通常の__getattr__トリックを実行してすべてを委任します。PS、ディスクストレージを意味するこの「ファイルオブジェクト」のアイデアが心配な場合は、ウィキペディアの「すべてはファイルです」を読んでください。

#3:最後に、PyPIの「非同期サブプロセス」モジュールの1つを取得するか、twistedまたは他の非同期フレームワークに含めて、それを使用できます。(これにより、デッドロックの問題を回避できますが、保証はされません。パイプを適切に保守する必要があります。)

于 2013-03-27T08:10:11.153 に答える
2

stdout出力は呼び出しプロセスに送られ、基本的にfromをキャプチャするself.cmdため、出力は他の場所に送られません。

出力を見たい場合は、「親」プロセスから印刷する必要があります。

于 2013-03-27T08:08:05.427 に答える