了解 Python 中的酸洗
Posted
技术标签:
【中文标题】了解 Python 中的酸洗【英文标题】:Understanding Pickling in Python 【发布时间】:2011-11-22 01:12:18 【问题描述】:我最近接到了一项任务,我需要将字典(其中每个键引用一个列表)以腌制形式放置。唯一的问题是我不知道腌制形式是什么。谁能指出一些好的资源的正确方向来帮助我学习这个概念?
【问题讨论】:
docs.python.org/library/pickle.html 是“泡菜”的第一个谷歌搜索结果,甚至超过了腌制蔬菜的***页面。 @Wooble:我知道它完全偏离主题,但 Google 搜索会因您的位置、搜索历史甚至电子邮件/聊天历史而异;)。但是,是的,+1 指向文档。 @0xc0de 对。对我来说,最高条目是腌制蔬菜。 :-) 我想我应该开始更多地编码。 另见:How to use pickle to store / load data 【参考方案1】:pickle 模块实现了一种基本但强大的算法,用于序列化和反序列化 Python 对象结构。
Pickling - 是将 Python 对象层次结构转换为字节流的过程,而 Unpickling - 是逆操作,将字节流转换回对象层次结构。
酸洗(和反酸洗)也称为序列化、编组或扁平化。
import pickle
data1 = 'a': [1, 2.0, 3, 4+6j],
'b': ('string', u'Unicode string'),
'c': None
selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)
output = open('data.pkl', 'wb')
# Pickle dictionary using protocol 0.
pickle.dump(data1, output)
# Pickle the list using the highest protocol available.
pickle.dump(selfref_list, output, -1)
output.close()
从腌制文件中读取 -
import pprint, pickle
pkl_file = open('data.pkl', 'rb')
data1 = pickle.load(pkl_file)
pprint.pprint(data1)
data2 = pickle.load(pkl_file)
pprint.pprint(data2)
pkl_file.close()
来源 - https://docs.python.org/2/library/pickle.html
【讨论】:
这只是我见过的最好的代码示例之一。格式精美,简洁明了。谢谢。 我不明白为什么data1 = pickle.load(pkl_file)
没有加载完整的文件(data.pkl)?
酸洗是否需要文件输出参数?您如何保留序列化对象以将其存储在其他地方?
对于使用 Python 3 的用户:pickle.dump(data1, output)
默认为 pickle.DEFAULT_PROTOCOL
(撰写此评论时的协议 3)而不是协议 0。【参考方案2】:
Pickling 是一种迷你语言,可用于将相关状态从 python 对象转换为字符串,其中该字符串唯一地表示该对象。然后 (un)pickling 可用于将字符串转换为活动对象,方法是从创建字符串的保存状态“重建”对象。
>>> import pickle
>>>
>>> class Foo(object):
... y = 1
... def __init__(self, x):
... self.x = x
... return
... def bar(self, y):
... return self.x + y
... def baz(self, y):
... Foo.y = y
... return self.bar(y)
...
>>> f = Foo(2)
>>> f.baz(3)
5
>>> f.y
3
>>> pickle.dumps(f)
"ccopy_reg\n_reconstructor\np0\n(c__main__\nFoo\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'x'\np6\nI2\nsb."
您在这里可以看到,pickle 不保存类的源代码,但确实存储了对类定义的引用。基本上,你几乎可以阅读挑选出来的字符串……它说(粗略翻译)“调用 copy_reg 的重构器,其中参数是 __main__.Foo
定义的类,然后做其他事情”。另一件事是实例的保存状态。如果您看得更深,您可以提取“字符串 x”设置为“整数 2”(大致为:S'x'\np6\nI2
)。这实际上是字典条目的腌制字符串的剪辑部分……dict
是f.__dict__
,即'x': 2
。如果您查看pickle
的源代码,它非常清楚地给出了从python 到腌制字节码的每种类型的对象和操作的翻译。
另请注意,酸洗语言有不同的变体。默认为协议 0,更易于阅读。还有协议 2,如下所示(以及 1,3 和 4,具体取决于您使用的 python 版本)。
>>> pickle.dumps([1,2,3])
'(lp0\nI1\naI2\naI3\na.'
>>>
>>> pickle.dumps([1,2,3], -1)
'\x80\x02]q\x00(K\x01K\x02K\x03e.'
同样,它仍然是酸洗语言的方言,您可以看到协议 0 字符串表示“获取列表,包括 I1、I2、I3”,而协议 2 更难阅读,但表示相同事物。第一个位 \x80\x02
表示它是协议 2 - 然后你有 ]
它说它是一个列表,然后你可以再次看到整数 1,2,3 在那里。同样,检查 pickle 的源代码以查看 pickle 语言的确切映射。
要将酸洗反转为字符串,请使用 load/loads。
>>> p = pickle.dumps([1,2,3])
>>> pickle.loads(p)
[1, 2, 3]
【讨论】:
作为一个初学者,我脑子里一直在想这个问题,泡菜在里面有什么作用?这个答案比其他答案更能解决这个问题。【参考方案3】:Pickling 只是序列化:将数据放入可以存储在文件中并在以后检索的表单中。以下是pickle
模块上的文档:
http://docs.python.org/release/2.7/library/pickle.html
【讨论】:
【参考方案4】:http://docs.python.org/library/pickle.html#example
import pickle
data1 = 'a': [1, 2.0, 3, 4+6j],
'b': ('string', u'Unicode string'),
'c': None
selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)
output = open('data.pkl', 'wb')
# Pickle dictionary using protocol 0.
pickle.dump(data1, output)
# Pickle the list using the highest protocol available.
pickle.dump(selfref_list, output, -1)
output.close()
【讨论】:
【参考方案5】:Python 中的 Pickling 用于序列化和反序列化 Python 对象,例如您的字典。我通常使用cPickle
模块,因为它比Pickle
模块快得多。
import cPickle as pickle
def serializeObject(pythonObj):
return pickle.dumps(pythonObj, pickle.HIGHEST_PROTOCOL)
def deSerializeObject(pickledObj):
return pickle.loads(pickledObj)
【讨论】:
Highest.protocol有什么用?【参考方案6】:有时我们想保存对象以便以后检索它们(即使在生成数据的程序终止之后)。或者我们想将对象传输给我们应用程序之外的某人或其他东西。 Pickle
module 用于对对象进行序列化和反序列化。
serializing object (Pickling): Create a representation of an object.
deserializing object (Unpickling): Re-load the object from representation.
dump: pickle to file
load: unpickle from file
dumps: returns a pickled representation. We can store it in a variable.
loads: unpickle from the supplied variable.
例子:
import pickle
print("Using dumps and loads to store it in variable")
list1 = [2, 4]
dict1 = 1: list1, 2: 'hello', 3: list1
pickle_dict = pickle.dumps(dict1)
print(pickle_dict)
dict2 = pickle.loads(pickle_dict)
print(dict2)
# obj1==obj2 => True
# obj1 is obj2 => False
print(id(dict1.get(1)), id(dict1.get(3)))
print(id(dict2.get(1)), id(dict2.get(3)))
print("*" * 100)
print("Using dump and load to store it in File ")
cars = ["Audi", "BMW", "Maruti 800", "Maruti Suzuki"]
file_name = "mycar.pkl"
fileobj = open(file_name, 'wb')
pickle.dump(cars, fileobj)
fileobj.close();
file_name = "mycar.pkl"
fileobj = open(file_name, 'rb')
mycar = pickle.load(fileobj)
print(mycar)
【讨论】:
【参考方案7】:Pickling 允许您序列化和反序列化 Python 对象结构。简而言之,Pickling 是一种将 python 对象转换为字符流的方法,以便该字符流包含在另一个 python 脚本中重构对象所需的所有信息。
import pickle
def pickle_data():
data =
'name': 'sanjay',
'profession': 'Software Engineer',
'country': 'India'
filename = 'PersonalInfo'
outfile = open(filename, 'wb')
pickle.dump(data,outfile)
outfile.close()
pickle_data()
【讨论】:
以上是关于了解 Python 中的酸洗的主要内容,如果未能解决你的问题,请参考以下文章