try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
数据流格式(协议)
pickle可以读写几种不同的、特定于Python的格式的文件,如documentation“Protocol version 0”中所述,称为protocols,因此是“人类可读的”。版本>;1是二进制的,可用的最高版本取决于所使用的Python版本。默认值也取决于Python版本。在Python 2中,默认的是协议版本0,但在Python 3.8.1中,默认的是协议版本4。在Python3.x中,模块中添加了一个pickle.DEFAULT_PROTOCOL,但Python2中不存在。
class Company:
def __init__(self, name, value):
self.name = name
self.value = value
def pickled_items(filename):
""" Unpickle a file of pickled data. """
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
print('Companies in pickle file:')
for company in pickled_items('company_data.pkl'):
print(' name: {}, value: {}'.format(company.name, company.value))
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import pickle
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>> with open('company.pkl', 'wb') as f:
... pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL)
...
>>>
现在关机,重新启动。。。
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import pickle
>>> with open('company.pkl', 'rb') as f:
... company1 = pickle.load(f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global
klass = self.find_class(module, name)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'Company'
>>>
你可以用anycache为你做这项工作。它考虑了所有细节:
pickle
模块来处理lambda
以及 python特性。假设您有一个创建实例的函数
myfunc
:Anycache在第一次调用
myfunc
,并将结果pickle到 在cachedir
中使用唯一标识符(取决于函数名及其参数)作为文件名的文件。 在任何连续的运行中,都会加载pickled对象。 如果在python运行之间保留了cachedir
,则pickled对象取自上一次python运行。有关更多详细信息,请参见documentation
您可以使用标准库中的
pickle
模块。 下面是它在示例中的一个基本应用:您还可以定义自己的简单实用程序,如下所示,它打开一个文件并向其中写入一个对象:
更新
由于这是一个非常流行的答案,我想谈谈一些稍微高级的使用主题。
cPickle
(或_pickle
)与pickle
实际上最好使用^{} 模块,而不是
pickle
,因为前者是用C编写的,而且速度更快。它们之间有一些细微的差别,但是在大多数情况下它们是等价的,C版本将提供非常优异的性能。切换到它并不容易,只需将import
语句更改为:在Python 3中,
cPickle
被重命名为_pickle
,但由于pickle
模块现在自动看到What difference between pickle and _pickle in python 3?,因此不再需要这样做。简而言之,您可以使用如下方法来确保代码在Python 2和3中都可用时始终使用C版本:
数据流格式(协议)
pickle
可以读写几种不同的、特定于Python的格式的文件,如documentation“Protocol version 0”中所述,称为protocols,因此是“人类可读的”。版本>;1是二进制的,可用的最高版本取决于所使用的Python版本。默认值也取决于Python版本。在Python 2中,默认的是协议版本0
,但在Python 3.8.1中,默认的是协议版本4
。在Python3.x中,模块中添加了一个pickle.DEFAULT_PROTOCOL
,但Python2中不存在。幸运的是,在每个调用中都有写
pickle.HIGHEST_PROTOCOL
的速记法(假设这是您想要的,而且您通常会这样做),只需使用文本号-1
-类似于通过负索引引用序列的最后一个元素。 所以,不要写:你可以写:
无论哪种方式,如果创建了用于多个pickle操作的
Pickler
对象,则只需指定一次协议:注意:如果您所处的环境运行的是不同版本的Python,那么您可能需要显式地使用(即硬代码)一个特定的协议号,所有这些协议号都可以读取(较新版本通常可以读取较早版本生成的文件)。
多个对象
尽管pickle文件可以包含任意数量的pickle对象,如上面的示例所示,但当它们的数量未知时,通常更容易将它们存储在某种大小可变的容器中,如
list
、tuple
或dict
,并在一次调用中将它们全部写入文件:稍后使用以下命令恢复列表和其中的所有内容:
主要优点是不需要知道保存了多少对象实例,以便以后加载它们(尽管这样做时不需要这些信息是可能的,但需要一些稍微特殊的代码)。请参阅相关问题Saving and loading multiple objects in pickle file?的答案,以了解执行此操作的不同方法的详细信息。我个人喜欢@Lutz Prechelt的answer最好的。下面是它改编的例子:
我认为假设对象是
class
是一个相当强的假设。如果不是class
呢?还有一个假设是对象没有在解释器中定义。如果它是在解释器中定义的呢?另外,如果属性是动态添加的呢?当一些python对象在创建后将属性添加到它们的__dict__
中时,pickle
不考虑这些属性的添加(即它“忘记”添加了它们——因为pickle
通过引用对象定义序列化)。在所有这些情况下,
pickle
和cPickle
都会让你非常失望。如果您希望保存一个
object
(任意创建),其中有属性(添加到对象定义中或之后)…您最好的选择是使用dill
,它可以序列化python中的几乎任何内容。我们从一节课开始
现在关机,重新启动。。。
哎哟……
pickle
处理不了。让我们试试dill
。我们将引入另一个对象类型(alambda
)以获得良好的度量。现在读一下文件。
它起作用了。
pickle
失败,而dill
不成功的原因是dill
将__main__
视为一个模块(在大多数情况下),并且还可以pickle类定义,而不是通过引用pickle(就像pickle
那样)。之所以dill
可以腌制lambda
,是因为它给它起了个名字……然后腌制魔法就可以发生。实际上,有一种更简单的方法保存所有这些对象,特别是如果您已经创建了很多对象。只需转储整个python会话,稍后再返回。
现在关掉你的电脑,去享受一杯浓咖啡或其他什么,然后回来。。。
唯一的主要缺点是
dill
不是python标准库的一部分。因此,如果不能在服务器上安装python包,就不能使用它。但是,如果能够在系统上安装python包,则可以使用
git+https://github.com/uqfoundation/dill.git@master#egg=dill
获得最新的dill
。您可以使用pip install dill
获得最新发布的版本。相关问题 更多 >
编程相关推荐