保存和加载对象并使用pickle

时间:2022-06-03 20:22:22

I´m trying to save and load objects using pickle module.
First I declare my objects:

我试图保存和加载对象使用´泡菜模块。首先我声明我的对象:

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

之后我打开一个名为“水果”的文件。(之前我创建了一个新的.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!

我´t´知道该做什么,因为我不了解这个信息。有人知道我如何装载我的“香蕉”吗?谢谢你!

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

7 个解决方案

#1


43  

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}

#2


19  

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

#3


10  

Always open in binary mode, in this case

在这种情况下,总是以二进制模式打开。

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

#4


8  

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 with statement.

一个更整洁的版本将使用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)

#5


4  

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.

我测试了你的代码,它是有效的。

#6


2  

It seems you want to save your class instances across sessions, and using pickle is a decent way to do this. However, there's a package called klepto that 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 klepto is 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是一种不错的方式。然而,有一个包叫做偷窃狂,抽象对象字典接口的储蓄,所以你可以选择pickle对象并将它们保存到一个文件中(如下所示),或pickle的对象并将其保存到一个数据库,而不是使用泡菜使用json或其他选项。klepto的好处在于,通过抽象到公共接口,它可以使您轻松地不需要记住如何通过pickle保存到文件或其他方式保存的底层细节。

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

Klepto works on python2 and python3.

Klepto研究的是python2和python3。

Get the code here: https://github.com/uqfoundation

在这里获取代码:https://github.com/uqfoundation

#7


0  

You can use anycache to do the job for you. Assuming you have a function myfunc which creates the instance:

您可以使用任何缓存为您完成这项工作。假设您有一个创建实例的函数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 myfunc at the first time and pickles the result to a file in cachedir using an unique identifier (depending on the the function name and the arguments) as filename. On any consecutive run, the pickled object is loaded.

Anycache第一次调用funmyc,并使用唯一标识符(取决于函数名和参数)作为文件名在cachedir中提取结果。在任何连续运行时,都会加载pickle对象。

If the cachedir is preserved between python runs, the pickled object is taken from the previous python run.

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

#1


43  

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}

#2


19  

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

#3


10  

Always open in binary mode, in this case

在这种情况下,总是以二进制模式打开。

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

#4


8  

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 with statement.

一个更整洁的版本将使用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)

#5


4  

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.

我测试了你的代码,它是有效的。

#6


2  

It seems you want to save your class instances across sessions, and using pickle is a decent way to do this. However, there's a package called klepto that 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 klepto is 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是一种不错的方式。然而,有一个包叫做偷窃狂,抽象对象字典接口的储蓄,所以你可以选择pickle对象并将它们保存到一个文件中(如下所示),或pickle的对象并将其保存到一个数据库,而不是使用泡菜使用json或其他选项。klepto的好处在于,通过抽象到公共接口,它可以使您轻松地不需要记住如何通过pickle保存到文件或其他方式保存的底层细节。

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

Klepto works on python2 and python3.

Klepto研究的是python2和python3。

Get the code here: https://github.com/uqfoundation

在这里获取代码:https://github.com/uqfoundation

#7


0  

You can use anycache to do the job for you. Assuming you have a function myfunc which creates the instance:

您可以使用任何缓存为您完成这项工作。假设您有一个创建实例的函数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 myfunc at the first time and pickles the result to a file in cachedir using an unique identifier (depending on the the function name and the arguments) as filename. On any consecutive run, the pickled object is loaded.

Anycache第一次调用funmyc,并使用唯一标识符(取决于函数名和参数)作为文件名在cachedir中提取结果。在任何连续运行时,都会加载pickle对象。

If the cachedir is preserved between python runs, the pickled object is taken from the previous python run.

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