我正在尝试使用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
答案 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