Python - Popen stdout をキャプチャし、コンソールに表示しますか?

StackOverflow https://stackoverflow.com/questions/1283061

  •  16-09-2019
  •  | 
  •  

質問

経由で開始された長時間実行プロセスから stdout をキャプチャしたい subprocess.Popen(...) だから私は使っています stdout=PIPE 引数として。

ただし、これは長時間実行されるプロセスであるため、出力を (パイプしていないかのように) コンソールに送信して、スクリプトのユーザーにスクリプトがまだ動作していることを知らせたいと考えています。

そもそもそんなことは可能なのでしょうか?

乾杯。

役に立ちましたか?

解決

あなたがパイプからそれを読んであなたは、単にそれをprintすることはできますか?

他のヒント

長時間実行されるサブプロセスが実行しているバッファリングにより、コンソール出力がぎくしゃくして UX が非常に悪くなる可能性があります。代わりに使用することを検討することをお勧めします 期待する (または、Windows では、 期待しています) このようなバッファリングを無効にして、サブプロセスからスムーズで定期的な出力を取得します。たとえば、(pexpect をインストールした後のほぼすべての unix-y システム上で):

>>> import pexpect
>>> child = pexpect.spawn('/bin/bash -c "echo ba; sleep 1; echo bu"', logfile=sys.stdout); x=child.expect(pexpect.EOF); child.close()
ba
bu
>>> child.before
'ba\r\nbu\r\n'

バとブがタイミングよく(1秒くらい)来ます。出力には通常の端末処理が適用されないため、キャリッジ リターンがそのまま残されることに注意してください。文字列を自分で後処理する必要があります (単純な処理です)。 .replace!-) 必要に応じて \n 行末マーカーとして (サブプロセスが stdout にバイナリ データを書き込んでいる場合に備えて、処理がないことが重要です。これにより、すべてのデータがそのまま残されることが保証されます)。

S.ロットのコメントは次のことを指摘しています サブプロセスを使用してリアルタイム出力を取得する そして Python での別のプロセスからの stdout のリアルタイムインターセプト

ここでの Alex の答えが彼の答え 1085071 と異なることに興味があります。他の 2 つの参照された質問の答えを使った私の簡単な小さな実験では、良い結果が得られました...

上記の Alex の回答に従って wexpect を調べましたが、コード内のコメントを読んで、それを使用することについてはあまり良い気分ではなかったと言わざるを得ません。

ここでのメタ質問は、pexpect/wexpect がいつ付属のバッテリーの 1 つになるのかということだと思います。

のpython2.6、Linux上で試験し、どこかに上記pty.openpty()提案に触発。それは

... W / Oバッファリング、これは正常に動作し作るためにしばらく時間がかかったので、出版
def call_and_peek_output(cmd, shell=False):
    import pty, subprocess
    master, slave = pty.openpty()
    p = subprocess.Popen(cmd, shell=shell, stdin=None, stdout=slave, close_fds=True)
    os.close(slave)
    line = ""
    while True:
        try:
            ch = os.read(master, 1)
        except OSError:
            # We get this exception when the spawn process closes all references to the
            # pty descriptor which we passed him to use for stdout
            # (typically when it and its childs exit)
            break
        line += ch
        sys.stdout.write(ch)
        if ch == '\n':
            yield line
            line = ""
    if line:
        yield line

    ret = p.wait()
    if ret:
        raise subprocess.CalledProcessError(ret, cmd)

for l in call_and_peek_output("ls /", shell=True):
    pass

また、あなたはTシャツにパイプあなたのプロセスをできるだけストリームの1つをキャプチャします。 sh -c 'process interesting stuff' | tee /dev/stderrの線に沿って何かます。

はもちろん、これが唯一のUnixライクなシステム上で動作します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top