保存并加载对象并使用pickle

我正尝试使用pickle模块来保存和加载对象。
首先我宣布我的对象:

 >>> class Fruits:pass ... >>> banana = Fruits() >>> banana.color = 'yellow' >>> banana.value = 30 

之后,我打开一个名为“Fruits.obj”的文件(以前我创build了一个新的.txt文件,并将其命名为“Fruits.obj”):

 >>> import pickle >>> filehandler = open(b"Fruits.obj","wb") >>> pickle.dump(banana,filehandler) 

这样做后,我closures我的会议,我开始了一个新的,我把下一个(试图访问它应该保存的对象):

 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 

至于你的第二个问题:

  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) 

你通常想要做的是使用上下文pipe理器打开文件并从中读取数据。 通过这种方式,文件将在块完成执行后自动closures,这也将帮助您将文件操作组织为有意义的块。

最后,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 

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

 file = 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 ab too 

所以把它换成:

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

它会工作:)


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

试试这一点的代码来写:

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

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

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

应该pipe用。

对于你的第二个错误,这个文件很可能是空的,这意味着你不小心清空了它,或者使用了错误的文件名或者其他东西。

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

我testing了你的代码,它工作。

看来你想保存你的class级实例跨会话,使用pickle是一个体面的方式来做到这一点。 但是,有一个名为klepto的包将对象的保存抽象为字典接口,因此您可以selectpickle对象并将其保存到文件中(如下所示),或者腌制对象并将其保存到数据库,或者替代使用pickle使用json,或许多其他选项。 关于klepto是,通过抽象到一个通用的界面,它可以很容易的,所以你不必记住如何通过酸洗保存到一个文件或其他方式的底层细节。

请注意,它适用于dynamic添加的类属性,腌菜不能做…

 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为你做这个工作。 假设你有一个创build实例的函数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 ,并使用唯一标识符(取决于函数名称和参数)作为文件名,将结果pickle到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