pickle
モジュールを使用してオブジェクトを保存およびロードしようとしています。
最初にオブジェクトを宣言します:
>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
その後、「Fruits.obj」というファイルを開きます(以前に新しい.txtファイルを作成し、「Fruits.obj」に名前を変更しました)。
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
これを行った後、セッションを閉じて新しいセッションを開始し、次のセッションを開始します(保存されるはずのオブジェクトへのアクセスを試みます)。
file = open("Fruits.obj",'r')
object_file = pickle.load(file)
しかし、私はこのメッセージを持っています:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
ValueError: read() from the underlying stream did notreturn bytes
私はこのメッセージを理解していないため、何をすべきかわかりません。誰でも私のオブジェクト「バナナ」をロードする方法を知っていますか?ありがとうございました!
編集:一部の人が推測しているように、
>>> import pickle
>>> file = open("Fruits.obj",'rb')
問題はありませんでしたが、次に私が置いたのは:
>>> object_file = pickle.load(file)
そして、私はエラーがあります:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError
2番目の問題について:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line
1365, in load encoding=encoding,
errors=errors).load() EOFError
ファイルの内容を読み取った後、ファイルポインターはファイルの最後になります。これ以上読み取るデータはありません。ファイルを最初から再度読み取るように、ファイルを巻き戻す必要があります。
file.seek(0)
ただし、通常行うことは、コンテキストマネージャを使用してファイルを開き、そこからデータを読み取ることです。この方法では、ブロックの実行が終了するとファイルが自動的に閉じられます。これは、ファイル操作を意味のあるチャンクに整理するのにも役立ちます。
最後に、cPickleはCのpickleモジュールのより高速な実装です。
In [1]: import cPickle
In [2]: d = {"a": 1, "b": 2}
In [4]: with open(r"someobject.pickle", "wb") as output_file:
...: cPickle.dump(d, output_file)
...:
# pickle_file will be closed at this point, preventing your from accessing it any further
In [5]: with open(r"someobject.pickle", "rb") as input_file:
...: e = cPickle.load(input_file)
...:
In [7]: print e
------> print(e)
{'a': 1, 'b': 2}
次は私のために働く:
class Fruits: pass
banana = Fruits()
banana.color = 'yellow'
banana.value = 30
import pickle
filehandler = open("Fruits.obj","wb")
pickle.dump(banana,filehandler)
filehandler.close()
file = open("Fruits.obj",'rb')
object_file = pickle.load(file)
file.close()
print(object_file.color, object_file.value, sep=', ')
# yellow, 30
バイナリとして読むのを忘れています。
書き込み部分には次のものがあります。
open(b"Fruits.obj","wb") # Note the wb part (Write Binary)
読み取り部分には次のものがあります。
file = open("Fruits.obj",'r') # Note the r part, there should be a b too
次のように置き換えます:
file = open("Fruits.obj",'rb')
そして、それは動作します:)
2番目のエラーについては、ファイルを適切に閉じ/同期していないことが原因である可能性が最も高くなります。
次のコードを試して書いてください。
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()
そして、これは(変更されていない)読むべき:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)
よりきれいなバージョンでは、with
ステートメントを使用します。
書き込みの場合:
>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>> pickle.dump(banana, fp)
読むために:
>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>> banana = pickle.load(fp)
この場合、常にバイナリモードで開きます。
file = open("Fruits.obj",'rb')
ファイルをバイナリモードで開いていません。
open("Fruits.obj",'rb')
動作するはずです。
2番目のエラーの場合、ファイルはほとんどの場合空です。これは、誤って空にしたか、間違ったファイル名などを使用したことを意味します。
(これは、セッションを本当に閉じたと仮定しています。そうでない場合は、書き込みと読み取りの間でファイルを閉じなかったためです)。
コードをテストしましたが、動作します。
セッション全体でクラスインスタンスを保存したいようです。pickle
を使用することは、これを行う適切な方法です。ただし、オブジェクトの辞書インターフェイスへの保存を抽象化するklepto
というパッケージがあります。そのため、オブジェクトをピクルしてファイルに保存するか(以下を参照)、オブジェクトをピクルして保存するかを選択できますデータベース、またはpickleを使用する代わりにjsonまたは他の多くのオプションを使用します。 klepto
の良いところは、共通のインターフェースに抽象化することで、ファイルへのピクルスなどを介して保存する方法の低レベルの詳細を覚えておく必要がないことです。
動的に追加されたクラス属性に対して機能することに注意してください。pickleではできません...
dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39)
[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.
>>> from klepto.archives import file_archive
>>> db = file_archive('fruits.txt')
>>> class Fruits: pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
>>>
>>> db['banana'] = banana
>>> db.dump()
>>>
その後、再起動します…
dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39)
[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.
>>> from klepto.archives import file_archive
>>> db = file_archive('fruits.txt')
>>> db.load()
>>>
>>> db['banana'].color
'yellow'
>>>
Klepto
は、python2およびpython3で動作します。
ここでコードを取得します: https://github.com/uqfoundation
anycache を使用してジョブを実行できます。インスタンスを作成する関数myfunc
があると仮定します。
from anycache import anycache
class Fruits:pass
@anycache(cachedir='/path/to/your/cache')
def myfunc()
banana = Fruits()
banana.color = 'yellow'
banana.value = 30
return banana
Anycacheは最初にmyfunc
を呼び出し、一意の識別子(関数名と引数に依存)をファイル名として使用して、結果をcachedir
のファイルにピクルします。連続して実行すると、漬物オブジェクトがロードされます。
pythonの実行間でcachedir
が保持される場合、ピクルスされたオブジェクトは前回のpythonの実行から取得されます。
関数の引数も考慮されます。リファクタリングされた実装も同様に機能します。
from anycache import anycache
class Fruits:pass
@anycache(cachedir='/path/to/your/cache')
def myfunc(color, value)
fruit = Fruits()
fruit.color = color
fruit.value = value
return fruit