10

Python のサブプロセスを介して呼び出したプロセスの出力をキャプチャして表示したいと考えています。

ファイルのようなオブジェクトを名前付きパラメーター stdout および stderr として渡すだけでよいと思いました

属性にアクセスしていることがわかりfilenoます。つまり、オブジェクトで何かを行っています。ただし、write()メソッドが呼び出されることはありません。私のアプローチは完全にオフですか、それとも何かが足りないだけですか?

class Process(object):
    class StreamWrapper(object):
        def __init__(self, stream):
            self._stream = stream
            self._buffer = []
        def _print(self, msg):
            print repr(self), msg
        def __getattr__(self, name):
            if not name in ['fileno']:
                self._print("# Redirecting: %s" % name)
            return getattr(self._stream, name)
        def write(self, data):
            print "###########"
            self._buffer.append(data)
            self._stream.write(data)
            self._stream.flush()
        def getBuffer(self):
            return self._buffer[:]
    def __init__(self, *args, **kwargs):
        print ">> Running `%s`" % " ".join(args[0])
        self._stdout = self.StreamWrapper(sys.stdout)
        self._stderr = self.StreamWrapper(sys.stderr)
        kwargs.setdefault('stdout', self._stdout)
        kwargs.setdefault('stderr', self._stderr)
        self._process = subprocess.Popen(*args, **kwargs)
        self._process.communicate()

アップデート:

私もやりたいのは、ANSI制御文字でカーソルを移動し、以前に出力したものを上書きすることです。それが正しい用語かどうかはわかりませんが、ここに私が意味したことの例を示します: 私はいくつかの GIT を自動化しようとしていますが、毎回新しい行に書き込むことなく自動的に更新される進行状況があります。

更新 2

サブプロセスの出力がすぐに表示されることが重要です。subprocess.PIPE を使用して出力をキャプチャし、手動で表示しようとしましたが、プロセスが完了してから出力を表示することしかできませんでした。ただし、出力をリアルタイムで見たいと思います。

4

4 に答える 4

12

プロセスの標準入力、標準出力、および標準エラー出力は、実際のファイル記述子である必要があります。(これは実際には Python によって課せられた制限ではなく、パイプが OS レベルでどのように機能するかということです。) したがって、別の解決策が必要になります。

stdout両方をstderrリアルタイムで追跡する場合は、非同期 I/O またはスレッドが必要になります。

  • 非同期 I/O:標準の同期 (= ブロッキング) I/O では、ストリームの 1 つへの読み取りがブロックされ、他のストリームへのリアルタイム アクセスができなくなる可能性があります。Unix を使用している場合は、この回答で説明されているように、ノンブロッキング I/O を使用できます。ただし、Windows では、この方法ではうまくいきません。Python での非同期 I/O の詳細と、いくつかの代替手段については、このビデオをご覧ください。

  • スレッド:この問題に対処するもう 1 つの一般的な方法は、リアルタイムで読み取りたいファイル記述子ごとに 1 つのスレッドを作成することです。スレッドは、割り当てられたファイル記述子のみを処理するため、I/O をブロックしても害はありません。

于 2010-12-02T14:15:13.137 に答える
0

こちらをご覧ください。

p = subprocess.Popen(cmd,
                 shell=True,
                 bufsize=64,
                 stdin=subprocess.PIPE,
                 stderr=subprocess.PIPE,
                 stdout=subprocess.PIPE)
于 2010-12-02T13:42:47.550 に答える
0

ファイルのようなものは十分に近いものではありません。これは、実際のファイル記述子を持つ実際のファイルでなければなりません。のパイプのサポートを使用subprocessし、必要に応じてパイプから読み取ります。

于 2010-12-02T13:43:01.630 に答える
-1

クラスの中にクラスがある理由はありますか?また、stdout と stderr は、try などの行のような任意のファイルを取ることができます。したがって、ストリームを変更するには、開いているファイルの種類または stringIO を渡すだけで十分です。

import sys
sys.stdout = open('test.txt','w')
print "Testing!"
sys.stdout.write('\nhehehe')
sys.stdout = sys.__stdout__
sys.exit(0)
于 2010-12-02T13:43:48.567 に答える