2

perlのラッパーの場合、Pythonで非ブロッキングサブプロセスが必要です(さまざまなタイプのシェルioがあります)。さらに、シェルの出力と戻り値に興味があります。戻り値が0の場合もありますが、コードは実際には何もしませんでした。
したがって、subprocess.call()(非ブロッキングですがシェル出力ではありません)またはsubprocess.Popen()(ブロッキングではあるがシェル出力)のいずれかを使用できます。

私はいくつかの読書をしましたが、唯一の解決策はこれを行うための別のキューを持っているように見えます。私が逃した簡単なものはありますか?

4

1 に答える 1

5

subprocess.Popen本質的にブロックしていません。あなたはまだ使用することができproc.stdin.write()ますproc.stdout.read(); 唯一の問題は、パイプがいっぱいになると、片側がブロックされたり、デッドロック[1]が発生したりするリスクがあることです。サブプロセスが少量のデータの読み取りまたは書き込みのみを行うことがわかっている場合は、それについて心配する必要はありません。

だからあなたはすることができます:

proc = subprocess.Popen(['perl', 'somescript.pl'], stdout=subprocess.PIPE)
buf = StringIO()
CHUNKSIZE = 1024  # how much to read at a time

while True:
    # do whatever other time-consuming work you want here, including monitoring
    # other processes...


    # this keeps the pipe from filling up
    buf.write(proc.stdout.read(CHUNKSIZE))

    proc.poll()
    if proc.returncode is not None:
        # process has finished running
        buf.write(proc.stdout.read())
        print "return code is", proc.returncode
        print "output is", buf.getvalue()

        break

より大きなアプリでは、これをイベントループやreactorなどで発生するようにスケジュールできます。


[1] OSは、一度に非常に多くのデータをパイプに収めることしかできません。サブプロセスとして実行catし、そのstdinに大量のデータを書き込むとします。 catデータがいっぱいになるまでそのデータを独自のstdoutに書き込み、その後、プログラムがstdoutからデータを読み取り、パイプを空にするまでブロックします。しかし、あなたのプログラムはまだstdinに書き込んでcatいて、それから読み取っていないので、パイプもいっぱいになります。両方のプロセスが書き込みのブロックでスタックし、もう一方が読み取るのを待ちますが、これは決して起こりません。

于 2013-02-28T21:13:27.640 に答える