2013-05-02 3 views
9

Pythonで実行時にオブジェクトのサイズを問い合わせるのと同様の質問がたくさんありました。いくつかの答えは、サブプロセスのメモリ量に制限を設定することを示唆しています。私はサブプロセスのメモリに制限を設定したくありません。ここに私が欲しいものがあります -Python - データサブプロセスの量を制限します.Popenで生成することができます

私はsubprocess.Popen()を使って外部プログラムを実行しています。プロセスが完了した後で、標準出力とエラーをprocess.stdout.readlines()process.stderr.readlines()で得ることができます。

エラーのあるプログラムが無限ループに入り、出力を生成し続けると、問題が発生します。 subprocess.Popen()は出力データをメモリに格納するので、この無限ループはメモリ全体を素早く消費し、プログラムは遅くなります。

解決策の1つは、タイムアウトでコマンドを実行できることです。しかし、プログラムは完了するまでに時間がかかります。大きな時間切れは、小さな時間をかけて無限のループを持つプログラムでは、それを持つ目的を破る。

コマンドで生成できるデータの量に200MBという上限を置くことができる簡単な方法はありますか?限界を超えた場合、コマンドは強制終了されるべきです。

+0

パイプバッファがいっぱいになると、子プロセスは遅くなるだけではありません。データを読むまで完全に停止します。複数のパイプを同時に読み取る必要がある場合は、スレッドまたは 'select'または' fcntl'モジュールを使用して、パイプをブロックせずに読み取ることができます。 – jfs

答えて

4

まず、データを格納するのはsubprocess.Popen()ではありませんが、 "us"サブプロセスと "our"サブプロセスの間のパイプです。

readlines()この場合、データを無期限にバッファリングし、最後にリストとして返すだけです(この場合、実際にデータを格納するのはこの関数です)。

あなたは

bytes = lines = 0 
for line in process.stdout: 
    bytes += len(line) 
    lines += 1 
    if bytes > 200000000 or lines > 10000: 
     # handle the described situation 
     break 

ような何かを行う場合は、あなたの質問に望んでいたとおりに行動することができます。しかし、後でデータを生成するのを止めるために、サブプロセスを終了させることを忘れないでください。

しかし、あなたにもstderrの世話をしたい場合は、select()などでprocess.communicate()の振る舞いを再現しようとする必要があり、かつ適切に行動するだろう。

+3

注意: 'if bytes ... or lines ...:'の内部で 'break 'を実行すると、この例ではパイプからデータを"消費 "しなくなり、サブプロセスは完全なstdoutパイプに書き込みます。 この時点で、データの消費(および破棄)を続行するか、子プロセスを終了する必要があります。 – fmoo

+0

@fmoo完全に正しい。サブプロセスが無限ループになる可能性があるため、データの破棄と廃棄は時間がかかる可能性がありますが、それを強制終了するのが適切であると思われます。 – glglgl

+0

OPが 'stderr'も読む必要がある場合、失敗する可能性があります。子プロセスがstderrパイプバッファをいっぱいにした場合、親プロセスは永遠に 'processから読み込みを試みます。子プロセスがstderrに書き込もうとする間に「stdout」を返します。 – jfs

1

あなたは

http://linux.about.com/library/cmd/blcmdl2_setrlimit.htm

RLIMITが開いているファイルのメモリ、CPUや数を制限するフラグを持っているが、どうやら何もの量を制限しないようにしたいものに簡単な答えがあるように思えません。 I/O。

既に説明したように、ケースを手動で処理する必要があります。

関連する問題