我创建了一个这样的对象:
company1.name = 'banana'
company1.value = 40
我想保存该对象。我怎样才能做到这一点?
你可以使用pickle
标准库中的模块。这是你的示例的基本应用:
import pickle
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
with open('company_data.pkl', 'wb') as output:
company1 = Company('banana', 40)
pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL)
company2 = Company('spam', 42)
pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL)
del company1
del company2
with open('company_data.pkl', 'rb') as input:
company1 = pickle.load(input)
print(company1.name) # -> banana
print(company1.value) # -> 40
company2 = pickle.load(input)
print(company2.name) # -> spam
print(company2.value) # -> 42
你还可以定义自己的简单实用程序,如下所示,该实用程序打开文件并向其中写入单个对象:
def save_object(obj, filename):
with open(filename, 'wb') as output: # Overwrites any existing file.
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
# sample usage
save_object(company1, 'company1.pkl')
更新资料
由于这是一个非常受欢迎的答案,因此,我想谈谈一些高级用法主题。
cPickle(或_pickle)与pickle
实际使用该cPickle模块几乎总是可取的,而不是pickle
因为该模块是用C编写的并且速度更快。它们之间有一些细微的差异,但是在大多数情况下它们是等效的,并且C版本将提供非常优越的性能。切换到它再简单不过,只需将import语句更改为此:
import cPickle as pickle
在Python 3中,它cPickle已被重命名_pickle,但是不再需要执行此操作,因为该pickle模块现在可以自动执行此操作-请参阅python 3中的pickle和_pickle有什么区别?。
总结是,你可以使用类似以下内容的代码来确保你的代码在Python 2和3中都可用时始终使用C版本:
try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
数据流格式(协议)
pickle可以使用多种不同的特定于Python的格式读写文件,这些格式称为文档中所述的协议,“协议版本0”为ASCII
,因此“易于阅读”。版本> 1
是二进制文件,可用的最高版本取决于所使用的Python版本。默认值还取决于Python
版本。在Python 2
中,默认值是Protocol
版本,但在Python 3.8.1中,它是Protocol版本。在Python 3.x中,该模块已添加,但在Python 2
中不存在。04pickle.DEFAULT_PROTOCOL
幸运的是,pickle.HIGHEST_PROTOCOL
在每个调用中都有一种写法(假设这就是你想要的,并且你通常会这样做),只需使用文字数字-1-类似于通过负索引引用序列的最后一个元素。因此,与其编写:
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
你可以这样写:
pickle.dump(obj, output, -1)
无论哪种方式,如果你创建了一个Pickler用于多个酸洗操作的对象,则只需指定一次协议:
pickler = pickle.Pickler(output, -1)
pickler.dump(obj1)
pickler.dump(obj2)
etc...
注意:如果你正在运行不同版本的Python的环境中,则可能需要显式使用(即,硬编码)所有这些协议都可以读取的特定协议编号(较新的版本通常可以读取较早版本产生的文件) 。
多个物件
虽然泡菜文件可以包含如上述样品中,当有这些数目不详的任何数量的腌制对象的,它往往更容易将其全部保存在某种可变大小的容器,就像一个list,tuple
或dict
写字一次调用即可将它们全部存储到文件中:
tech_companies = [
Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18)
]
save_object(tech_companies, 'tech_companies.pkl')
然后使用以下命令还原列表及其中的所有内容:
with open('tech_companies.pkl', 'rb') as input:
tech_companies = pickle.load(input)
主要优点是你无需知道保存了多少个对象实例即可在以后加载它们(尽管如果没有该信息就可以这样做,但它需要一些专门的代码)。请参阅相关问题的答案在pickle文件中保存和加载多个对象?有关执行此操作的不同方法的详细信息。我个人最喜欢@Lutz Prechelt的答案。它适用于此处的示例:
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))
java 持久实体
我想写一个脚本,它将2 GB的数据从硬盘加载到内存中,然后当其他程序请求时,它必须得到一个输入,并根据输入对这个数据进行一些计算。对我来说,重要的是将这2 GB的数据持久地保存在内存中,以加快计算速度,更重要的是避免巨大的I/O负载。 我应该如何将数据永远保存在内存中?或者更一般地说,我应该如何在Python中解决这样的问题?
问题内容: 我对 SQLite3 和 Python 3 做错了。也许我误解了SQLite数据库的概念,但是我希望即使关闭应用程序后,数据仍存储在数据库中?当我插入数据并重新打开应用程序时,插入物消失了,数据库为空。 这是我的小数据库: 我在哪里做错了? 问题答案: 调用以将事务刷新到磁盘。 程序退出时,最后一个未完成的事务将回滚到最后一个提交。(或更准确地说,回滚是由下一个打开数据库的程序完成的。
我使用StreamRefs在集群中的参与者之间建立流式连接。目前,在writing节点中,我手动将传入消息保存到日志文件中,但我想知道是否可以将其替换为persistent,用于写入,以及persistent,用于从Akka Persistence journal启动actor时读取。我一直在考虑用Persistent actor的
主要内容:一、数据持久化,二、持久化的形式,三、源码分析,四、总结一、数据持久化 redis做为一种内存型数据库,做持久化,个人感觉略有鸡肋的意思。似乎有一种,别人有,自己不有也不行的感觉。以目前Redis主流的应用方式,如果仔细分析,基本上都是在内存中即可完成,对持久化没要求或者说不大。再举一个反例,如果内存中有几百G甚至更多的数据,真要是整体当机,恢复的时间基本就是灾难。 目前基本应用仍然是以关系型数据库或者其它数据库(如Hadoop,Mysql等)为持久化
创建新的Shelf # shelve_create.py import shelve with shelve.open('test_shelf.db') as s: s['key1'] = { 'int': 10, 'float': 9.5, 'string': 'Sample data', } # shelve_existing