9

メモリを大量に消費する Python アプリケーション (数百 MB から数 GB) があります。
メインアプリケーションを実行する必要がある非常に小さなLinux実行可能ファイルがいくつかあります。

child = Popen("make html", cwd = r'../../docs', stdout = PIPE, shell = True)
child.wait()

これらの外部ユーティリティを (1 回、長いメイン プロセスの実行の最後に) を使用して実行するsubprocess.Popenと、OSError: [Errno 12] Cannot allocate memory.
理由がわかりません... 要求されたプロセスが小さいです。
システムには、さらに多くのシェルに十分なメモリがあります。

私はLinux(Ubuntu 12.10、64ビット)を使用しているので、サブプロセスがForkを呼び出していると思います。
Fork は既存のプロセスを fork するため、消費されるメモリ量が 2 倍になり、失敗しますか??
「コピーオンライト」はどうなりましたか?

フォークせずに (または少なくともメモリをコピーせずに) 新しいプロセスを生成できますか?

関連している:

fork()、vfork()、exec()、clone()の違い

fork () & メモリ割り当て動作

Python subprocess.Popen OSError でエラーが発生: [Errno 12] 一定期間後にメモリを割り当てることができません

subprocess.Popen を使用した Python メモリ割り当てエラー

4

1 に答える 1

4

本当の解決策 (つまり、vfork を使用するサブプロセスの代替実装) が間もなく提供されるようには見えません。それでは、かわいいハックはいかがですか?プロセスの開始時に、メモリ フットプリントが小さいスレーブをスポーンし、サブプロセスをスポーンする準備を整え、メイン プロセスの存続期間中、それとのオープンな通信を維持します。

以下は rfoo ( http://code.google.com/p/rfoo/ ) を rfoosocket と呼ばれる名前付き unix ソケットで使用する例です (rfoo がサポートする他の接続タイプや別の RPC ライブラリを使用することもできます):

サーバ:

import rfoo
import subprocess

class MyHandler(rfoo.BaseHandler):
    def RPopen(self, cmd):
        c = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
        c.wait()
        return c.stdout.read()

rfoo.UnixServer(MyHandler).start('rfoosocket')

クライアント:

import rfoo

# Waste a bunch of memory before spawning the child. Swap out the RPC below
# for a straight popen to show it otherwise fails. Tweak to suit your
# available system memory.
mem = [x for x in range(100000000)]

c = rfoo.UnixConnection().connect('rfoosocket')

print rfoo.Proxy(c).RPopen('ls -l')

生成されたサブプロセスとのリアルタイムのコプロセス対話が必要な場合、このモデルはおそらく機能しませんが、ハックできる可能性があります。おそらく、Popen に渡すことができる利用可能な引数をクリーンアップする必要があります。特定のニーズに基づいていますが、それはすべて比較的簡単なはずです。

また、クライアントの起動時にサーバーを起動し、終了時にソケット ファイル (またはポート) をクリーンアップするように管理することも簡単です。

于 2013-07-04T00:43:46.327 に答える