47

サブプロセスモジュールを次のように使用したいと思います。

  1. 実行に時間がかかる可能性のある新しいプロセスを作成します。
  2. キャプチャstdout(またはstderr、あるいは両方、一緒にまたは別々に)
  3. サブプロセスからのデータを受信時に処理します。おそらく受信したすべての行でイベントを発生させるか(wxPythonなど)、または単に今のところそれらを出力します。

Popenを使用してプロセスを作成しましたが、communicate()を使用すると、プロセスが終了すると、データが一度に届きます。

(を使用して)ブロッキングを行う別のスレッドを作成するとreadline()、プロセスが終了するまで、このメソッドでも行を取得できません。(bufsizeとして何を設定しても)myprocess.stdoutstdout = subprocess.PIPE

恐ろしくなく、複数のプラットフォームでうまく機能するこれに対処する方法はありますか?

4

10 に答える 10

8

動作しないように見えるコードで更新します (とにかく Windows 上で)

class ThreadWorker(threading.Thread):
    def __init__(self, callable, *args, **kwargs):
        super(ThreadWorker, self).__init__()
        self.callable = callable
        self.args = args
        self.kwargs = kwargs
        self.setDaemon(True)

    def run(self):
        try:
            self.callable(*self.args, **self.kwargs)
        except wx.PyDeadObjectError:
            pass
        except Exception, e:
            print e



if __name__ == "__main__":
    import os
    from subprocess import Popen, PIPE

    def worker(pipe):
        while True:
            line = pipe.readline()
            if line == '': break
            else: print line

    proc = Popen("python subprocess_test.py", shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)

    stdout_worker = ThreadWorker(worker, proc.stdout)
    stderr_worker = ThreadWorker(worker, proc.stderr)
    stdout_worker.start()
    stderr_worker.start()
    while True: pass
于 2009-05-17T19:16:53.203 に答える
7

stdout はバッファリングされるため、そのバッファがいっぱいになるか、サブプロセスが終了するまで何も取得できません。

サブプロセスからフラッシュstdoutするか、stderr を使用するか、非バッファ モードで stdout を変更してみてください。

于 2009-05-17T15:51:49.717 に答える
2

これが私のために働いたものです:

cmd = ["./tester_script.bash"]
p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
while p.poll() is None:
    out = p.stdout.readline()
    do_something_with( out, err )

あなたの場合、サブプロセスへの参照をワーカースレッドに渡して、スレッド内でポーリングを行うことができます。2 つのスレッドが同じサブプロセスをポーリング (および対話) したときにどのように動作するかはわかりませんが、機能する可能性があります。

また、そのままのものであることに注意してくださいwhile p.poll() is None:。Pythonのように置き換えないでください(正常終了のリターンコード)も考慮されます.while not p.poll()0False

于 2009-12-22T10:06:00.163 に答える
2

問題は、サブプロセスによるバッファリングされた出力の使用にあるようです。比較的少量の出力が作成される場合、サブプロセスが終了するまでバッファリングされる可能性があります。いくつかの背景はここにあります:

于 2009-05-17T15:53:38.610 に答える
1

subprocess.Popen を使用して、C# プロジェクトの 1 つの .exe を実行し、出力を Python ファイルにリダイレクトできます。print()C# コンソール (を使用Console.WriteLine()) に出力されているすべての情報を Python コンソールに表示できるようになりました。

Python コード:

from subprocess import Popen, PIPE, STDOUT

p = Popen('ConsoleDataImporter.exe', stdout = PIPE, stderr = STDOUT, shell = True)

while True:
    line = p.stdout.readline()
    print(line)
    if not line:
        break

これは、.NET プロジェクトのコンソール出力を行ごとに取得し、プロジェクトの終了時に囲んでいる while ループから抜け出します。これは2つのpythonファイルでも機能すると思います。

于 2016-08-04T19:05:36.527 に答える
1

ノンブロッキング readlines でpexpect [ http://www.noah.org/wiki/Pexpect]を使用すると、この問題が解決します。これは、パイプがバッファリングされているため、アプリの出力がパイプによってバッファリングされているため、バッファがいっぱいになるかプロセスが停止するまで、その出力に到達できません。

于 2010-05-18T15:42:43.557 に答える
1

私もこの問題に遭遇しました。この問題は、stderr も読み取ろうとしているために発生します。エラーがない場合、stderr から読み取ろうとするとブロックされます。

Windows では、ファイル記述子を poll() する簡単な方法はありません (Winsock ソケットのみ)。

したがって、解決策は stderr から読み取ろうとしないことです。

于 2010-02-24T17:37:13.897 に答える
1

これはよく知られた Python の制限のようです 。PEP 3145などを参照してください。

于 2013-03-29T07:39:02.090 に答える
0

これには pexpect モジュールを使用しましたが、問題なく動作するようです。http://sourceforge.net/projects/pexpect/

于 2009-09-21T18:51:59.427 に答える