質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

5414閲覧

Python、メモリ、もうわからんぞ。。。。

kenmero

総合スコア30

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2019/04/19 05:26

現在、大量データ(DBから全件取得)を取り込もうとしたときに、
メモリ領域が足りずにデータが途中までしか取り込めないなんて
ケースを想定した際の対応をどうすればいいか考えております。

OS:rhel7.6
言語:Python3.7

<教えてほしいこと>
・Pythonが保持できるメモリ領域の最大は?
また、その領域は変更可能か?
・メモリ領域で抱えられないデータを取り込もうとしたとき、
そのデータはどのように処理されるのか?

テストして試したいんですけど、
その方法もわからずに、瞑想してます。。。。

どれか一つでもいいので教えていただけることがあったら
教えてください!!!<(_ _)>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mather

2019/04/19 05:34

いちいちタイトルが雑です。質問したいことを明確にタイトルに記載してください。
guest

回答3

0

ベストアンサー

Pythonが保持できるメモリ領域の最大は?

スワップ領域もありますが、基本的には、PC に搭載しているメモリ量と考えてよいのではないでしょうか。

Linux であれば、free コマンド、Widnwos であればタスクマネージャーでメモリ使用量を確認できます。

また、Python のコードで確認したい場合は、メモリなどシステムに関する情報を確認できる psutil というライブラリがあります。

psutil documentation — psutil 5.6.2 documentation

python

1import psutil 2 3info = psutil.virtual_memory() 4print(info) 5# svmem(total=67497332736, available=54389481472, percent=19.4, used=10516938752, 6# free=17032527872, active=18114748416, inactive=24519929856, buffers=431259648, 7# cached=39516606464, shared=2041597952, slab=6908645376) 8 9print('available: {:.2f} GB'.format(info.available / 2**30)) # free: 50.65 GB

メモリ領域で抱えられないデータを取り込もうとしたとき、そのデータはどのように処理されるのか?

アプリケーションがクラッシュするなど何が起こるかはわかりません。動作未定義と思います。
使用できるメモリ量以上のメモリを使うようなプログラムを書くことは NG です。

そもそもメモリとは処理に使用するデータを一時的に置いておく場所なので、「DB の中身を全部メモリに展開しようとする」という使い方自体がおかしいと思います。

使用する分だけ DB からメモリに展開する、使い終わったら開放するといったコードを記載するのがよいでしょう。Python の場合、ガレージコレクションがあるため、参照されなくなったオブジェクトは自動で破棄されます。

追記

・メモリ、スワップ上を超えたデータが取得された場合、OS側でエラーとなり、

メモリ不足が発生した場合、エラーといっても try-except 文で補足できるような形の例外が発生することは期待できず、アプリケーションがクラッシュする、最悪 OS を巻き込んで落ちるといった可能性もあります。
なので、そもそもメモリ不足が発生するような状況はアプリケーションの仕様上起こらないようにする必要があります。

大量データで処理をするときに、yeildを用いて一行ずつデータを展開させるようにすれば、少しはよくなるかも?

回答の内容で「使用する分だけ DB からメモリに展開する」というのは、例えば、10万件のレコードがあるテーブルの中身を表示するとして、それを一度に全部取得して、表示しようとしたら、メモリ不足になるかもしれません。
そうするのではなく、一度に100件ずつ表示するように制限すれば、必要なメモリは100件分だけなので、少ないメモリ量で済みます。
「1 ~ 100」行表示して、「次へ」をクリックしたら、次の「101 ~ 200」行を表示するといった具合です。
この場合、「101 ~ 200」行を表示する際は、「1 ~ 100」行のデータは不要なので、メモリに置いておく必要はなくなり、メモリ上には常に100行分のデータだけ展開されていることになります。

ここ (teratail) もそうですが、沢山のデータがある場合は一度に表示されるのは10件ずつとか件数が決まっており、「次へ」をクリックしてページ送りするような作りになっています。

投稿2019/04/19 05:46

編集2019/04/19 09:02
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kenmero

2019/04/19 07:59 編集

psutil というコマンドがあるんですね!確認してみます! アプリケーションがクラッシュするなど何が起こるかはわかりません。動作未定義と思います。 使用できるメモリ量以上のメモリを使うようなプログラムを書くことは NG です。 >そもそもメモリとは処理に使用するデータを一時的に置いておく場所なので、 >「DB の中身を全部メモリに展開しようとする」という使い方自体がおかしいと思います。 確かにそうですね。sqlで取得データを絞れればよかったんですが、、 大量にとってきたデータをジェネレーターを用いて処理していくのも 一つの手になりますか?
tiitoi

2019/04/19 08:04 編集

psutil はコマンドではなく、Python のライブラリです。 標準ライブラリではないので、pip で入れる必要があります。(pip install psutil) > 大量にとってきたデータをジェネレーターを用いて処理していくのも 一つの手になりますか? ジェネレーターを使用する場合は、呼ばれるたびに一定範囲の件数分取得する SQL を発行して、取得したデータを yield で返すとかですかね。 例えば、データベースのテーブルの中身を閲覧するソフト等ありますが、1度に表示できる件数が100件とか決まっていて、ページ送りしていく仕様になっていると思います。
kenmero

2019/04/19 08:43

お返事ありがとうございます!!!! 恥ずかしい、コマンドって書いてましたか。。。w 今更ですが、今回想定としては、CMDBのデータをRest APIを用いて取得することが 前提となります。取得データはJSON形式で帰ってきますので、 戻り値から、json関数を用いてdict変数に代入して使用するイメージでいます。 なんか混乱してきたのですが、それを踏まえて考えると、 ・メモリ、スワップ上を超えたデータが取得された場合、OS側でエラーとなり、 ・メモリ、スワップ上に展開できた場合でも、メモリ領域は食いっぱなしだから  処理速度は低下する可能性大だよね?  <その時の対応策として>   大量データで処理をするときに、yeildを用いて一行ずつデータを展開させるように   すれば、少しはよくなるかも? って感じですかね。。。。w
tiitoi

2019/04/19 09:04

追記しました。Python のジェネレーターを使うというのは、今回の件の解決策としてはあまり関係ないような気がします。 重要なのは、データベースから表示する分だけ SQL 文を発行してとってくるということです。10万件のレコードを表示するアプリケーションを作る場合、100件ずつ表示してページ送りするような作りにすれば、メモリの問題は発生しません。
kenmero

2019/04/19 10:52

追記ありがとうございます。 大変わかりやすく書いてくださったおかげで、すぐイメージできました。 確かに、使用可能なメモリ領域より大きいデータが来るような 作りとしては、プログラムの仕組みとして破綻していますね。 物理的に対応できないなら、プログラム以前の問題ですしね。。。 そうならない為には、やはりtiitoiさんがおっしゃる通り DBの取得を制御をかけて取ってくる必要がありますね。 100件ずつ表示してページ送りできる方法があるか探してみます! 最後まで付き合って頂き、ありがとうございました! 本当に助かりました!!!
guest

0

回答ではありませんが、先日LLVM(clang)をうっかりデバッグ付きでコンパイルしたらメモリ16Gとスワップ32Gを食いつぶしてmakeがコケました^^;。メモリ不足ならOS側で対応してくれます。matherさんが仰るようにメモリ容量なんか気にせずにソースを書いて実行してみましょう。

投稿2019/04/19 07:10

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kenmero

2019/04/19 07:53

デバッグ付で行うとメモリを大量に食うんですね。。。。w 勉強になります。ありがとうございます!!!
guest

0

「スワップ領域」
https://begi.net/read/base/09.html

投稿2019/04/19 05:35

mather

総合スコア6753

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mather

2019/04/19 05:45

思い込みばかりで杞憂するよりコードを書きましょう。 最初はメモリ管理などを気にしなくてもいいです。 実際にコードを書いて確認した上で「正常に動かない。どうしよう。」というときに自力で解決できなければここに質問してください。
kenmero

2019/04/19 07:40

お返事遅くなりました 思い込みが先走り手を動かすのを忘れていました。。。 的確なご指摘ありがとうございます<(_ _)>
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問