保存和加载对象并使用pickle

时间:2010-12-25 15:17:18

标签: python object 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

7 个答案:

答案 0 :(得分:60)

至于你的第二个问题:

 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}

答案 1 :(得分:29)

以下适用于我:

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

答案 2 :(得分:15)

你忘记把它作为二进制文件阅读。

在你的写作部分,你有:

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)

答案 3 :(得分:12)

始终以二进制模式打开,在本例中为

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

答案 4 :(得分:4)

您没有以二进制模式打开文件。

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

应该工作。

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

(假设您确实关闭了会话。如果没有,那就是因为您没有在写入和读取之间关闭文件。)

我测试了你的代码,但它确实有用。

答案 5 :(得分: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

答案 6 :(得分:0)

您可以使用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并将结果调到a cachedir中的文件使用唯一标识符(取决于函数名称和参数)作为文件名。 在任何连续运行中,都会加载pickle对象。

如果在python运行之间保留cachedir,那么pickle对象将从之前的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