保存和加载对象并使用 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
615862 次浏览

在这种情况下,始终以二进制模式打开

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

你没有用二进制模式打开文件。

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

应该可以。

对于您的第二个错误,该文件很可能是空的,这意味着您无意中清空了它或使用了错误的文件名或其他东西。

(这是假设你真的结束了你的会话。如果没有,那是因为您没有在写和读之间关闭文件)。

我测试了你的代码,很管用。

你也忘了把它读成二进制了。

在你的写作部分你有:

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')

它会起作用的:)


至于第二个错误,很可能是由于没有正确关闭/同步文件造成的。

尝试编写下面这段代码:

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

至于你的第二个问题:

 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 _pickle as 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

您似乎希望在不同的会话之间保存类实例,而使用 pickle是一种不错的方法。然而,有一个名为 klepto的包将对象的保存抽象为一个字典接口,因此您可以选择 pickle 对象并将其保存到一个文件(如下所示) ,或 pickle 对象并将其保存到一个数据库,或者不使用 pickle 使用 json,或者许多其他选项。klepto的好处在于,通过抽象到一个公共接口,它使之变得简单,这样您就不必记住如何通过 pickle 保存文件或其他方式保存的底层细节。

注意,它适用于动态添加的类属性,而 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

假设你有一个函数 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并将结果腌制到 使用唯一标识符(取决于函数名和参数)作为文件名。 在任何连续运行中,将加载 pickled 对象。

如果在两次 Python 运行之间保留了 cachedir,那么 pickled 对象将从前一次 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