模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。 "pickling" 是将 Python 对象及其所拥有的层次结构转化为一个字节流的过程,而 "unpickling" 是相反的操作,会将(来自一个 binary file 或者 bytes-like object 的)字节流转化回一个对象层次结构。 pickling(和 unpickling)也被称为“序列化”, “编组” 1 或者 “平面化”。而为了避免混乱,此处采用术语 “封存 (pickling)” 和 “解封 (unpickling)”。
pickle
模块 并不安全。 你只应该对你信任的数据进行 unpickle 操作。
构建恶意的 pickle 数据来 在解封时执行任意代码 是可能的。 绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。
请考虑使用 hmac 来对数据进行签名,确保数据没有被篡改。
在你处理不信任数据时,更安全的序列化格式如 json 可能更为适合。
在 pickle 协议和 JSON (JavaScript Object Notation) 之间有着本质上的差异:
要将Python对象序列化为二进制数据,可以使用pickle.dump()
函数。以下是一个简单的示例,将一个Python列表保存到文件中:
import pickle data = [1, 2, 3, 4, 5] # 打开一个文件以写入二进制数据 with open('data/data.pkl', 'wb') as file: pickle.dump(data, file)
在上述代码中,使用pickle.dump()
函数将data列表序列化为二进制数据,并将其保存到名为data.pkl的文件中。参数'wb'表示以二进制写入模式打开文件。
要从文件中加载并反序列化二进制数据,可以使用pickle.load()函数。以下是加载data.pkl文件并还原Python对象的示例:
import pickle # 打开文件以读取二进制数据 with open('data/data.pkl', 'rb') as file: loaded_data = pickle.load(file) print("反序列化 %s" % loaded_data)
在上述代码中,使用pickle.load()
函数从data.pkl文件中加载数据,并将其还原为Python对象。
pickle模块的工作原理涉及到将Python对象转换为一种可序列化的中间格式,然后再将该中间格式序列化为二进制数据。这个中间格式是一个自包含的表示对象的字典,其中包含了对象的数据和其类型信息。
当使用pickle.dump()
序列化对象时,pickle 模块首先创建一个包含对象数据和类型信息的中间字典。然后,它将该字典转换为二进制数据。反序列化时,pickle模块将二进制数据还原为中间字典,然后再从字典中还原Python对象。
这种方法使pickle模块非常灵活,因为它可以序列化几乎所有Python对象,包括自定义对象,只要它们可以在中间字典中表示。
pickle模块在以下情况下非常有用:
尽管pickle非常方便,但在使用它时需要注意一些事项:
以下是一个示例代码,演示如何使用pickle模块来序列化和反序列化一个自定义Python对象:
import pickle class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"Person(name='{self.name}', age={self.age})" # 创建一个自定义对象 person = Person("Alice", 30) # 序列化并保存到文件 with open('data/person.pkl', 'wb') as file: pickle.dump(person, file) # 从文件中加载并反序列化 with open('data/person.pkl', 'rb') as file: loaded_person = pickle.load(file) print(loaded_person) # 输出: Person(name='Alice', age=30)
在上述代码中,我们首先定义了一个自定义类Person,然后创建了一个Person对象。我们使用pickle将该对象序列化为二进制数据,然后再从二进制数据中反序列化还原对象。