[解決済み】オブジェクトの保存 (データ永続化)
質問
このようなオブジェクトを作成しました。
company1.name = 'banana'
company1.value = 40
このオブジェクトを保存したいのですが。どうすればいいでしょうか?
どのように解決するのですか?
を使用することができます。
pickle
というモジュールが標準ライブラリに含まれています。
ここでは、その初歩的な応用例を紹介します。
import pickle
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
with open('company_data.pkl', 'wb') as outp:
company1 = Company('banana', 40)
pickle.dump(company1, outp, pickle.HIGHEST_PROTOCOL)
company2 = Company('spam', 42)
pickle.dump(company2, outp, pickle.HIGHEST_PROTOCOL)
del company1
del company2
with open('company_data.pkl', 'rb') as inp:
company1 = pickle.load(inp)
print(company1.name) # -> banana
print(company1.value) # -> 40
company2 = pickle.load(inp)
print(company2.name) # -> spam
print(company2.value) # -> 42
また、次のような独自の簡単なユーティリティを定義して、ファイルを開き、そこに1つのオブジェクトを書き込むこともできます。
def save_object(obj, filename):
with open(filename, 'wb') as outp: # Overwrites any existing file.
pickle.dump(obj, outp, pickle.HIGHEST_PROTOCOL)
# sample usage
save_object(company1, 'company1.pkl')
更新情報
この回答はとても人気があるので、少し高度な使用法について触れてみたいと思います。
cPickle
(または
_pickle
) 対
pickle
を実際に使用することが望ましい場合がほとんどです。
cPickle
モジュールではなく
pickle
というのも、前者はC言語で書かれており、はるかに高速だからです。両者には微妙な違いがありますが、ほとんどの場面で同等であり、C言語版の方がはるかに優れた性能を発揮します。C言語版に切り替えるのはこれ以上ないほど簡単です。
import
ステートメントをこれに変更します。
import cPickle as pickle
Python 3では
cPickle
という名前に変更されました。
_pickle
を使用する必要がなくなりました。
pickle
モジュールが自動的に行うようになりました。
Python 3でpickleと_pickleの違いは何ですか?
.
要するに、以下のようなものを使って、あなたのコードが確実に 常に は、Python 2 と 3 の両方で利用可能な場合は、C バージョンが使用されます。
try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
データストリームのフォーマット(プロトコル)
pickle
と呼ばれるPython固有のフォーマットでファイルの読み書きができます。
プロトコル
で説明されているように
ドキュメント
プロトコルバージョン0"はASCIIであるため、人間が読むことが可能です。バージョン 0 はバイナリで、使用されている Python のバージョンにより、最も高いものが使用できます。デフォルトもPythonのバージョンに依存します。Python 2 では、デフォルトはプロトコルバージョンでした。
0
しかし、Python 3.8.1では、プロトコルバージョン
4
. Python 3.x では、このモジュールには
pickle.DEFAULT_PROTOCOL
が追加されていますが、これはPython 2には存在しません。
幸いなことに
pickle.HIGHEST_PROTOCOL
を使うだけです。
-1
- 負のインデックスを使用してシーケンスの最後の要素を参照するのと同じです。
つまり、代わりにこう書きます。
pickle.dump(obj, outp, pickle.HIGHEST_PROTOCOL)
書けばいいんだよ。
pickle.dump(obj, outp, -1)
いずれにせよ、プロトコルを一度だけ指定する必要があるのは
Pickler
オブジェクトを複数のpickle操作で使用することができます。
pickler = pickle.Pickler(outp, -1)
pickler.dump(obj1)
pickler.dump(obj2)
etc...
備考 : 異なるバージョンのPythonが動作している環境では、おそらくすべてのPythonが読める特定のプロトコル番号を明示的に使用(つまりハードコード)したいでしょう(後のバージョンでは、一般的に以前のバージョンで生成されたファイルを読むことができます)。
複数のオブジェクト
pickleファイル中
できること
は、上記のサンプルのように任意の数のpickleオブジェクトを含みますが、未知の数のpickleオブジェクトがある場合、多くの場合、それらをすべて
list
,
tuple
または
dict
を一回の呼び出しでファイルに書き込む。
tech_companies = [
Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18)
]
save_object(tech_companies, 'tech_companies.pkl')
でリストとその中のすべてを後で復元します。
with open('tech_companies.pkl', 'rb') as inp:
tech_companies = pickle.load(inp)
主な利点は、後でロードし直すために保存されているオブジェクトインスタンスの数を知る必要がないことです(ただし、その情報なしでロードする場合は は 可能ですが、少し特殊なコードが必要です)。関連する質問に対する回答を参照してください。 pickleファイルに複数のオブジェクトを保存して読み込む? をご覧ください。個人的には、@Lutz Prechelt の 回答 が一番良いので、以下のサンプルコードではその方法を用いています。
class Company:
def __init__(self, name, value):
self.name = name
self.value = value
def pickle_loader(filename):
""" Deserialize a file of pickled objects. """
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
print('Companies in pickle file:')
for company in pickle_loader('company_data.pkl'):
print(' name: {}, value: {}'.format(company.name, company.value))
関連
-
[解決済み] 関数デコレータを作成し、それらを連鎖させるには?
-
[解決済み] 複数の例外を1行でキャッチする(ブロックを除く)
-
[解決済み] 辞書を値で並べ替えるにはどうしたらいいですか?
-
[解決済み] PandasでDataFrameの行を反復処理する方法
-
[解決済み] バイトを文字列に変換する
-
[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
-
[解決済み] 文字列をfloatやintにパースするにはどうしたらいいですか?
-
[解決済み] 改行やスペースを入れずに印刷する方法
-
[解決済み] インスタンスのクラス名を取得する?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonによるjieba分割ライブラリ
-
Python interpreted model libraryによる機械学習モデル出力の可視化 Shap
-
Pythonの@decoratorsについてまとめてみました。
-
[解決済み】ilocが「IndexError: single positional indexer is out-of-bounds」を出す。
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】numpy: true_divide で無効な値に遭遇
-
[解決済み】TypeErrorを取得しました。エントリを持つ子テーブルの後に親テーブルを追加しようとすると、 __init__() missing 1 required positional argument: 'on_delete'
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み】SyntaxError: デフォルト以外の引数がデフォルトの引数に続く
-
[解決済み] TypeError: 'DataFrame' オブジェクトは呼び出し可能ではない