Python 保存和加载对象并使用pickle
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4530611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Saving and loading objects and using pickle
提问by Peterstone
I′m trying to save and load objects using picklemodule.
First I declare my objects:
我正在尝试使用pickle模块保存和加载对象。
首先我声明我的对象:
>>> class Fruits:pass
...
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
After that I open a file called 'Fruits.obj'(previously I created a new .txt file and I renamed 'Fruits.obj'):
之后,我打开一个名为“Fruits.obj”的文件(之前我创建了一个新的 .txt 文件并将其重命名为“Fruits.obj”):
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
After do this I close my session and I began a new one and I put the next (trying to access to the object that it supposed to be saved):
完成此操作后,我关闭会话并开始一个新会话,然后放置下一个(尝试访问它应该保存的对象):
file = open("Fruits.obj",'r')
object_file = pickle.load(file)
But I have this message:
但我有这样的消息:
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
I don′t know what to do because I don′t understand this message. Does anyone know How I can load my object 'banana'? Thank you!
我不知道该怎么做,因为我不明白这个消息。有谁知道我如何加载我的对象“香蕉”?谢谢!
EDIT:As some of you have sugested I put:
编辑:正如你们中的一些人所建议的那样,我提出:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
There were no problem, but the next I put was:
没有问题,但我提出的下一个问题是:
>>> object_file = pickle.load(file)
And I have error:
我有错误:
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
回答by ismail
Always open in binary mode, in this case
在这种情况下,始终以二进制模式打开
file = open("Fruits.obj",'rb')
回答by Lennart Regebro
You didn't open the file in binary mode.
您没有以二进制模式打开文件。
open("Fruits.obj",'rb')
Should work.
应该管用。
For your second error, the file is most likely empty, which mean you inadvertently emptied it or used the wrong filename or something.
对于您的第二个错误,该文件很可能是空的,这意味着您无意中将其清空或使用了错误的文件名或其他内容。
(This is assuming you really did close your session. If not, then it's because you didn't close the file between the write and the read).
(这是假设您确实关闭了会话。如果没有,那是因为您没有在写入和读取之间关闭文件)。
I tested your code, and it works.
我测试了你的代码,它有效。
回答by Wolph
You're forgetting to read it as binary too.
您也忘记将其作为二进制读取。
In your write part you have:
在你的写作部分,你有:
open(b"Fruits.obj","wb") # Note the wb part (Write Binary)
In the read part you have:
在阅读部分,您有:
file = open("Fruits.obj",'r') # Note the r part, there should be a b too
So replace it with:
所以将其替换为:
file = open("Fruits.obj",'rb')
And it will work :)
它会起作用:)
As for your second error, it is most likely cause by not closing/syncing the file properly.
至于您的第二个错误,很可能是由于未正确关闭/同步文件造成的。
Try this bit of code to write:
试试这段代码来写:
>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()
And this (unchanged) to read:
这(不变)阅读:
>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)
A neater version would be using the withstatement.
更简洁的版本将使用该with语句。
For writing:
对于写作:
>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>> pickle.dump(banana, fp)
For reading:
阅读:
>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>> banana = pickle.load(fp)
回答by Jim Brissom
As for your second problem:
至于你的第二个问题:
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
After you have read the contents of the file, the file pointer will be at the end of the file - there will be no further data to read. You have to rewind the file so that it will be read from the beginning again:
读取文件内容后,文件指针将位于文件末尾 - 将不再有数据可读取。您必须倒带文件,以便从头开始再次读取它:
file.seek(0)
What you usually want to do though, is to use a context manager to open the file and read data from it. This way, the file will be automatically closed after the block finishes executing, which will also help you organize your file operations into meaningful chunks.
不过,您通常想要做的是使用上下文管理器打开文件并从中读取数据。这样,文件将在块完成执行后自动关闭,这也将帮助您将文件操作组织成有意义的块。
Finally, cPickle is a faster implementation of the pickle module in C. So:
最后,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}
回答by martineau
The following works for me:
以下对我有用:
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
回答by Mike McKerns
It seems you want to save your class instances across sessions, and using pickleis a decent way to do this. However, there's a package called kleptothat abstracts the saving of objects to a dictionary interface, so you can choose to pickle objects and save them to a file (as shown below), or pickle the objects and save them to a database, or instead of use pickle use json, or many other options. The nice thing about kleptois that by abstracting to a common interface, it makes it easy so you don't have to remember the low-level details of how to save via pickling to a file, or otherwise.
似乎您想跨会话保存类实例,使用pickle是一种不错的方法。但是,有一个名为的包将klepto对象的保存抽象到字典接口,因此您可以选择pickle对象并将它们保存到文件中(如下所示),或者pickle对象并将它们保存到数据库中,或者代替使用 pickle 使用 json 或许多其他选项。好的一点klepto是,通过抽象到一个公共接口,它变得很容易,因此您不必记住如何通过酸洗保存到文件或其他方式的低级细节。
Note that It works for dynamically added class attributes, which pickle cannot do...
请注意,它适用于动态添加的类属性,而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()
>>>
Then we restart…
然后我们重新开始……
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'
>>>
Kleptoworks on python2 and python3.
Klepto适用于 python2 和 python3。
Get the code here: https://github.com/uqfoundation
在此处获取代码:https: //github.com/uqfoundation
回答by c0fec0de
You can use anycacheto do the job for you. Assuming you have a function myfuncwhich creates the instance:
您可以使用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 calls myfuncat the first time and pickles the result to a
file in cachedirusing an unique identifier (depending on the the function name and the arguments) as filename.
On any consecutive run, the pickled object is loaded.
Anycachemyfunc在第一次调用并将结果腌制到文件中,cachedir使用唯一标识符(取决于函数名和参数)作为文件名。在任何连续运行中,都会加载腌制对象。
If the cachediris preserved between python runs, the pickled object is taken from the previous python run.
如果cachedir在 python 运行之间保留了 ,pickled 对象将从之前的 python 运行中获取。
The function arguments are also taken into account. A refactored implementation works likewise:
函数参数也被考虑在内。重构的实现同样有效:
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

