web-dev-qa-db-ja.com

オブジェクトの保存と読み込み、およびpickleの使用

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
85
Peterstone

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}
61
Jim Brissom

次は私のために働く:

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
31
martineau

バイナリとして読むのを忘れています。

書き込み部分には次のものがあります。

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)
17
Wolph

この場合、常にバイナリモードで開きます。

file = open("Fruits.obj",'rb')
12
ismail

ファイルをバイナリモードで開いていません。

open("Fruits.obj",'rb')

動作するはずです。

2番目のエラーの場合、ファイルはほとんどの場合空です。これは、誤って空にしたか、間違ったファイル名などを使用したことを意味します。

(これは、セッションを本当に閉じたと仮定しています。そうでない場合は、書き込みと読み取りの間でファイルを閉じなかったためです)。

コードをテストしましたが、動作します。

4
Lennart Regebro

セッション全体でクラスインスタンスを保存したいようです。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

2
Mike McKerns

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
0
c0fec0de