私はこのようなオブジェクトを作成しました:
company1.name = 'banana'
company1.value = 40
このオブジェクトを保存したいと思います。どうやってやるの?
protocol=pickle.HIGHEST_PROTOCOL
。私の答えは、漬物の代わりにもなります。
私はこのようなオブジェクトを作成しました:
company1.name = 'banana'
company1.value = 40
このオブジェクトを保存したいと思います。どうやってやるの?
protocol=pickle.HIGHEST_PROTOCOL
。私の答えは、漬物の代わりにもなります。
回答:
pickle
標準ライブラリのモジュールを使用できます。これがあなたの例への基本的なアプリケーションです:
import pickle
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
with open('company_data.pkl', 'wb') as output:
company1 = Company('banana', 40)
pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL)
company2 = Company('spam', 42)
pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL)
del company1
del company2
with open('company_data.pkl', 'rb') as input:
company1 = pickle.load(input)
print(company1.name) # -> banana
print(company1.value) # -> 40
company2 = pickle.load(input)
print(company2.name) # -> spam
print(company2.value) # -> 42
ファイルを開いてそれに単一のオブジェクトを書き込む次のような独自のシンプルなユーティリティを定義することもできます。
def save_object(obj, filename):
with open(filename, 'wb') as output: # Overwrites any existing file.
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
# sample usage
save_object(company1, 'company1.pkl')
これは非常に人気のある回答なので、少しだけ高度な使用法のトピックについて触れたいと思います。
cPickle
(または_pickle
)vspickle
前者はCで記述されており、はるかに高速であるため、実際にcPickle
モジュールを使用する方がほとんど常に望ましい方法pickle
です。それらの間には微妙な違いがありますが、ほとんどの場合それらは同等であり、Cバージョンは非常に優れたパフォーマンスを提供します。これに切り替えるのは簡単ではありません。import
ステートメントを次のように変更してください。
import cPickle as pickle
Python 3ではcPickle
に名前が変更されました_pickle
が、pickle
モジュールが自動的に行うようになったため、これを行う必要はなくなりました。Python3のpickleと_pickleの違いを参照してください。。
要約すると、次のようなものを使用して、Python 2と3の両方で使用可能な場合、コードが常に Cバージョンを使用するようにすることができます。
try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
pickle
ドキュメントで説明されているように、プロトコルと呼ばれるいくつかの異なるPython固有の形式でファイルを読み書きできます。「プロトコルバージョン0」はASCIIであるため、「人間が読める形式」です。バージョン> 0はバイナリであり、使用可能な最も高いバージョンは、使用されているPythonのバージョンによって異なります。デフォルトはPythonのバージョンにも依存します。Python 2ではデフォルトはプロトコルバージョンでしたが、Python 3.8.1ではプロトコルバージョンです。Python 3.xではモジュールが追加されていましたが、Python 2にはありません。0
4
pickle.DEFAULT_PROTOCOL
幸いにもpickle.HIGHEST_PROTOCOL
、すべての呼び出しでそれを書くための省略形があります(それがあなたが望むことであり、通常はそうすることを前提とします)。リテラル番号を使用します-1
—負のインデックスを介してシーケンスの最後の要素を参照するのと同じです。だから、書く代わりに:
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
あなたはただ書くことができます:
pickle.dump(obj, output, -1)
どちらの方法でもPickler
、複数のピクル操作で使用するオブジェクトを作成した場合は、プロトコルを1回指定するだけです。
pickler = pickle.Pickler(output, -1)
pickler.dump(obj1)
pickler.dump(obj2)
etc...
注:異なるバージョンのPythonを実行している環境にいる場合、おそらくすべてのユーザーが読み取ることができる特定のプロトコル番号を明示的に使用(ハードコード)する必要があります(後のバージョンは通常、以前のバージョンで作成されたファイルを読み取ることができます)。 。
ピクルスファイルをしながらすることができ、それらの未知の数があるとき、上記のサンプルのように漬けたオブジェクトの任意の数を、含まれている、それは、可変サイズのコンテナのいくつかの並べ替えでそれらのすべてを保管のようにする方が簡単だlist
、tuple
またはdict
書き込みそれらすべてを1回の呼び出しでファイルに追加します。
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 input:
tech_companies = pickle.load(input)
主な利点は、後でロードするために保存されているオブジェクトインスタンスの数を知る必要がないことです(その情報なしでそうすることは可能ですが、少し特殊なコードが必要です)。関連する質問への回答を参照してください複数のオブジェクトをpickleファイルに保存してロードしますか?これを行うさまざまな方法の詳細については。個人的には、@ Lutz Precheltの答えが一番好きです。これは、ここの例に適応したものです。
class Company:
def __init__(self, name, value):
self.name = name
self.value = value
def pickled_items(filename):
""" Unpickle a file of pickled data. """
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
print('Companies in pickle file:')
for company in pickled_items('company_data.pkl'):
print(' name: {}, value: {}'.format(company.name, company.value))
company1
しcompany2
ます。削除Company
して何が起こるかを見せてみませんか?
オブジェクトがであると想定することは、かなり強力な仮定だと思いますclass
。ない場合はどうなりclass
ますか?オブジェクトがインタープリターで定義されていないという前提もあります。インタプリタで定義されている場合はどうなりますか?また、属性が動的に追加された場合はどうなりますか?一部のpythonオブジェクト__dict__
に作成後の属性が追加されている場合pickle
、それらの属性の追加は考慮されません(つまりpickle
、オブジェクト定義への参照によってシリアル化されるため、追加されたことが「忘れられます」。
すべてのこれらのケースでは、pickle
とcPickle
恐ろしくあなたを失敗する可能性があります。
object
(任意に作成された)属性を保存する場合(オブジェクト定義に追加された後、またはその後に)…を使用するのが最善です。dill
これは、Pythonのほとんどすべてをシリアル化できるを使用することです。
クラスから始めます…
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>> with open('company.pkl', 'wb') as f:
... pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL)
...
>>>
シャットダウンして再起動します...
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pickle
>>> with open('company.pkl', 'rb') as f:
... company1 = pickle.load(f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global
klass = self.find_class(module, name)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'Company'
>>>
エラーpickle
が発生しました。やってみようdill
。lambda
適切な測定のために、別のオブジェクトタイプ(a )を投入します。
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> with open('company_dill.pkl', 'wb') as f:
... dill.dump(company1, f)
... dill.dump(company2, f)
...
>>>
そして今、ファイルを読みます。
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> with open('company_dill.pkl', 'rb') as f:
... company1 = dill.load(f)
... company2 = dill.load(f)
...
>>> company1
<__main__.Company instance at 0x107909128>
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>>
できます。pickle
失敗する理由と失敗dill
しない理由は、(ほとんどの場合)モジュールのようにdill
扱わ__main__
れ、参照によるピクル化の代わりに(そうするようにpickle
)クラス定義をピクルすることができるからです。その理由dill
pickle化することができますがlambda
、それはそれに名前を与えることを...そして、酸洗魔法が発生する可能性があります。
実際に、作成したオブジェクトがたくさんある場合は特に、これらすべてのオブジェクトを保存する簡単な方法があります。Pythonセッション全体をダンプし、後で戻ってくるだけです。
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> dill.dump_session('dill.pkl')
>>>
コンピューターをシャットダウンし、エスプレッソなどを楽しんでから、後で戻ってきます...
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('dill.pkl')
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>> company2
<function <lambda> at 0x1065f2938>
唯一の大きな欠点は、それdill
がpython標準ライブラリの一部ではないことです。したがって、サーバーにPythonパッケージをインストールできない場合は、使用できません。
ただし、システムにPythonパッケージをインストールできる場合は、を使用して最新バージョンdill
を入手できますgit+https://github.com/uqfoundation/dill.git@master#egg=dill
。そして、あなたはで最新のリリースされたバージョンを得ることができますpip install dill
。
TypeError: __new__() takes at least 2 arguments (1 given)
使用しようとするとdill
、オーディオファイルが含まれてかなり複雑なオブジェクトで(有望に見えました)。
TypeError
正確には何をしているのですか?これは通常、クラスインスタンスをインスタンス化するときに、引数の数が間違っていることを示しています。これが上記の質問のワークフローの一部ではない場合、別の質問として投稿したり、メールで私に送信したり、dill
githubページに問題として追加したりできますか?
dill
問題ではありませんでした。
dil
でも私はくれMemoryError
ます!そうcPickle
、pickle
そしてhickle
。
あなたはanycacheを使ってあなたのために仕事をすることができます。それはすべての詳細を考慮します:
pickle
モジュールを拡張して、Pythonのlambda
すべての優れた機能を処理します。myfunc
インスタンスを作成する関数があると仮定します。
from anycache import anycache
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
@anycache(cachedir='/path/to/your/cache')
def myfunc(name, value)
return Company(name, value)
Anycacheはmyfunc
最初に呼び出し、cachedir
(関数名とその引数に応じて)一意の識別子をファイル名として使用して、結果をファイルにピクルします。連続して実行すると、ピクルされたオブジェクトがロードされます。cachedir
がPythonの実行間で保持される場合、ピクルされたオブジェクトは以前のPythonの実行から取得されます。
詳細については、ドキュメントを参照してください
anycache
たとえば、class
またはのようなコンテナの複数のインスタンスを保存するためにどのように使用しますかlist
(これは関数を呼び出した結果ではありませんでした)。
company1
あなたの質問からpython3 を使った簡単な例。
import pickle
# Save the file
pickle.dump(company1, file = open("company1.pickle", "wb"))
# Reload the file
company1_reloaded = pickle.load(open("company1.pickle", "rb"))
ただし、この回答で述べたように、ピクルスは失敗することがよくあります。したがって、実際に使用する必要がありますdill
。
import dill
# Save the file
dill.dump(company1, file = open("company1.pickle", "wb"))
# Reload the file
company1_reloaded = dill.load(open("company1.pickle", "rb"))