Parameter | Details |
object | 要存储的对象 |
file | 将包含对象的打开文件 |
protocol | 用于序列化对象的协议(可选参数) |
buffer | 包含序列化对象的字节对象 |
1: 使用 Pickle 序列化和反序列化对象
pickle 模块实现了一种算法,可以将任意 Python 对象转换为一系列字节。这个过程也被称为 序列化 对象。表示对象的字节流随后可以被传输或存储,并且稍后可以被重建以创建一个具有相同特征的新对象。
对于最简单的代码,我们使用 dump() 和 load() 函数。
序列化对象
import pickle
# 一个由 pickle 支持的任意对象集合。
data = {
'a': [1, 2.0, 3, 4+6j],
'b': ("character string", b"byte string"),
'c': {None, True, False}
}
with open('data.pickle', 'wb') as f:
# 使用可用的最高协议序列化 'data' 字典。
pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
反序列化对象
import pickle
with open('data.pickle', 'rb') as f:
# 使用的协议版本会自动检测,因此我们不需要指定它。
data = pickle.load(f)
使用 pickle 和字节对象
也可以使用 dumps 和 loads 函数将对象序列化为字节对象或将字节对象反序列化为对象,这两个函数分别等同于 dump 和 load。
serialized_data = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
# type(serialized_data) 是 bytes
deserialized_data = pickle.loads(serialized_data)
# deserialized_data == data
2: 自定义 Pickle 数据
有些数据无法被序列化。还有些数据由于其他原因不应该被序列化。
可以通过定义 __getstate__ 方法来指定哪些数据将被序列化。这个方法必须返回可序列化的数据。
相对应的是 __setstate__ 方法:它会接收 __getstate__ 创建的数据,并且必须用来初始化对象。
class A(object):
def __init__(self, important_data):
self.important_data = important_data
# 添加无法序列化的数据:
self.func = lambda: 7
# 添加不应被序列化的数据,因为它会快速过期:
self.is_up_to_date = False
def __getstate__(self):
return [self.important_data] # 只需要序列化这个
def __setstate__(self, state):
self.important_data = state[0]
self.func = lambda: 7 # 只是某个硬编码的不可序列化函数
self.is_up_to_date = False # 即使在序列化之前它是 True 也一样
现在可以这样操作:
>>> a1 = A('very important')
>>>
>>> s = pickle.dumps(a1) # 调用 a1.__getstate__()
>>>
>>> a2 = pickle.loads(s) # 调用 a1.__setstate__(['very important'])
>>> a2
<__main__.a object at 0x0000000002742470>
>>> a2.important_data
'very important'
>>> a2.func()
7
这里的实现将一个包含一个值的列表序列化:[self.important_data]。这只是一个示例,__getstate__ 可以返回任何可序列化的数据,只要 __setstate__ 知道如何反向操作即可。一个不错的选择是返回一个包含所有值的字典:{'important_data': self.important_data}。
注意,构造函数不会被调用!在前面的例子中,实例 a2 是在 pickle.loads 中创建的,而从未调用过 A.__init__,因此 A.__setstate__ 必须初始化 __init__ 本应初始化的所有内容。