web-dev-qa-db-ja.com

回避方法[Errno 12]サブプロセスモジュールの使用により発生したメモリエラーを割り当てることができません

完全な動作テストケース

もちろん、ローカルマシンとリモートマシンのメモリによって、アレイサイズは異なります。

z1 = numpy.random.Rand(300000000,2);
for i in range(1000):
  print('*******************************************\n'); 
  direct_output = subprocess.check_output('ssh blah@blah "ls /"', Shell=True);
  direct_output = 'a'*1200000; 
  a2 = direct_output*10;
  print(len(direct_output));

現在のユースケース

私のユースケースが次のように役立つ場合:

Dbクエリを発行し、結果のテーブルをリモートマシンに保存します。次に、ネットワークを介してそれらを転送し、分析を行います。これまでのところ、私はPythonで次のようなことをしていました:

#run a bunch of queries before hand with the results in remote files

....
counter = 0
mergedDataFrame = None
while NotDone:
  output = subprocess.check_output('ssh blah@blah cat /data/file%08d'%(counter))
  data = pandas.read_csv(...)
  #do lots of analysis, append, merge, numpy stuff etc...
  mergedDataFrame = pandas.merge(...)
  counter += 1

ある時点で、check_outputコマンドで次のエラーを受け取ります。[Errno 12]メモリを割り当てることができません

背景

以下の質問のおかげで、私は何が間違っているのかを知っていると思います。多数のソリューションが投稿されており、どのソリューションが[Errno 12] fork/cloneを使用したサブプロセス実装に関連するメモリ割り当てエラーを回避できないかを判断しようとしています。

Python subprocess.Popen "OSError:[Errno 12]メモリを割り当てることができません" これにより、根本的な診断が得られ、別のスクリプトの生成などの回避策が提案されます。

理解Python fork and memory allocation errors rfooを使用してfork/cloneのサブプロセスの制限を回避し、子プロセスを生成し、メモリをコピーするなどを提案します...クライアントサーバーモデル

Pythonを使用したSSHの最も簡単な方法は何ですか? ですが、メモリの制限とfork/cloneの実装のためにサブプロセスを使用できないという追加の制約がありますか?ソリューションは、paramikoまたはその上に構築されたものを使用することを提案し、他のものはサブプロセスを提案します(私の場合はうまくいかないことがわかりました)。

他の同様の質問がありましたが、答えはファイル記述子が犯人である(この場合はそうではない)、システムにさらにRAMを追加する(これはできません)、x64にアップグレードする) (私はすでにx64を使用しています。)ENOMEMの問題についてのヒントがいくつかあります。いくつかの回答では、subprocess.Popen(私の場合はcheck_output)がプロセスを適切にクリーニングしていないかどうかを確認しようとしていますが、S.Lottなどのように見えますサブプロセスのコード自体が適切にクリーンアップされることに同意します。

Github https://github.com/paramiko/paramiko/search?q=Popen&type=Code でソースコードを検索しましたが、proxy.pyファイルでサブプロセスを使用しているようです。

実際の質問

これは、最終的にparamikoが上記のPopenソリューションを使用していることを意味しますか?pythonメモリフットプリントが大きくなり、クローン/フォークの実装によりPopen呼び出しが繰り返されると問題が発生しますか?

Paramikoが動作しない場合、クライアント側のみのソリューションで私が探していることを行う別の方法がありますか?または、クライアント/サーバー/ソケットソリューションが必要ですか?もしそうなら、rfoo、tornado、またはzeromq、http転送のいずれかがここで動作しますか?

64ビットLinux 8GBメインメモリを実行しています。 RAMを追加購入するオプションを追求したくありません。

36
Paul

メモリが不足している場合は、スワップメモリ​​を増やしてください。または、スワップがまったく有効になっていない可能性があります。 Ubuntuでは(他のディストリビューションでも動作するはずです)、次の方法でスワップを確認できます。

$Sudo swapon -s

空の場合は、スワップが有効になっていないことを意味します。 1GBのスワップを追加するには:

$Sudo dd if=/dev/zero of=/swapfile bs=1024 count=1024k
$Sudo mkswap /swapfile
$Sudo swapon /swapfile

fstabに次の行を追加して、スワップを永続化します。

$Sudo vim /etc/fstab

     /swapfile       none    swap    sw      0       0 

ソースと詳細情報は here にあります。

52
Nima

メモリが不足している場合は、サブプロセスが同時にメモリに多くの情報を読み込もうとしていることが原因である可能性があります。ローカルファイルへのリダイレクトを使用する以外の解決策は、一度に少しずつ読み取ることができるstdin/stdoutペアでpopenのような機能を使用することです。

2
dstromberg

これはそれを行う必要があります:

http://docs.python.org/3.3/library/subprocess.html#replacing-os-popen-os-popen2-os-popen

そうすれば、一度に全部を読むのではなく、行またはブロックを読むことができます。

1
dstromberg