6

subprocess モジュールを使用して実行しているコマンドがいくつかあります。次に、出力の行をループしたいと思います。ドキュメントには、私がしていない data_stream.stdout.read を実行しないと書かれていますが、それを呼び出す何かを実行している可能性があります。次のように出力をループしています。

for line in data_stream.stdout:
   #do stuff here
   .
   .
   .

これにより、data_stream.stdout からの読み取りなどのデッドロックが発生する可能性がありますか?それとも、通信コードを使用するがそのすべての呼び出しを処理するように、この種のループ用に Popen モジュールが設定されていますか?

4

4 に答える 4

9

サブプロセスと通信している場合、つまり stdout からの読み取りだけでなく stdin への書き込みも行っている場合、デッドロックについて心配する必要があります。これらのパイプはキャッシュされる可能性があるため、この種の双方向通信を行うことは非常に禁止されています。

data_stream = Popen(mycmd, stdin=PIPE, stdout=PIPE)
data_stream.stdin.write("do something\n")
for line in data_stream:
  ...  # BAD!

ただし、data_stream を構築するときに stdin (または stderr) を設定していない場合は、問題ありません。

data_stream = Popen(mycmd, stdout=PIPE)
for line in data_stream.stdout:
   ...  # Fine

双方向通信が必要な場合は、 communicate を使用しください。

于 2009-08-14T13:57:35.347 に答える
6

サブプロセスへの書き込み、サブプロセスからの読み取り、再度の書き込みなどを混在させないでください。パイプのバッファリングは、デッドロックのリスクがあることを意味します。可能であれば、最初にサブプロセスに書き込む必要があるすべてを書き込み、そのパイプを閉じてから、サブプロセスが言う必要があるすべてを読み取ります。communicateデータ量が大きすぎてメモリに収まらない場合 (そうであれば、「手動で」同じ効果を得ることができます)。

よりきめ細かい対話が必要な場合は、代わりにpexpectを参照してください。Windows を使用している場合はwexpectを参照してください。

于 2009-08-14T14:38:51.783 に答える
4

サブプロセスからの出力が少量から中程度であれば、SilentGhost/chrispy の回答は問題ありません。ただし、出力が多すぎてメモリに快適にバッファリングできない場合もあります。そのような場合、やるべきことはstart()プロセスであり、いくつかのスレッドを生成します.1つは読み取り用でchild.stdout、もう1つはサブプロセスです。次に、サブプロセスを終了する必要があります。child.stderrchildwait()

これが実際の仕組みcommunicate()です。独自のスレッドを使用する利点は、サブプロセスからの出力を生成時に処理できることです。たとえば、私のプロジェクトでは、python-gnupgこの手法を使用して、生成された GnuPG 実行可能ファイルからステータス出力を読み取りますcommunicate()。このプロジェクトのソースを調べてください。関連するものはモジュールにありますgnupg.py

于 2009-08-14T14:33:29.670 に答える
0

data_stream.stdoutは標準出力ハンドルです。あなたはそれをループしてはいけません。communicateのタプルを返します(stdoutdata, stderr)。これstdoutdataは、自分の仕事をするために使用する必要があります。

于 2009-08-14T13:54:15.570 に答える