Python 中的 pickle
模块是实现了二进制协议的,用于序列化和反序列化一个 Python 对象结构。
Pickling : 这是一个将 Python 对象层次结构转换为字节流的过程
Unpickling : 它是 Pickling 过程的逆过程,将字节流被转换为 Python 对象层次结构。
pickle 模块提供的序列化和反序列化接口
pickle
模块提供了两个主要的方法用于序列化和反序列化 Python 对象。
方法 | 说明 |
---|---|
dumps() | 该方法用于序列化一个 Python 对象层次结构为二进制字节流 |
loads() | 该方法用于反序列化一个数据流为 Python 对象层次结构 |
为了更好的控制序列化和反序列化,这两个方法会分别创建 Pickler
和 Unpickler
对象。
pickle 模块提供的常量
pickle
模块提供了两个常量
常量 | 说明 |
---|---|
pickle.HIGHEST_PROTOCOL | 这是一个整数值,表示可用的最高协议版本。它可以作为协议版本的参数传递给 dump() 和 dumps() 函数 |
pickle.DEFAULT_PROTOCOL | 这是一个整数值,表示用于 pickling 的默认协议,其值可能小于最高协议的值 |
pickle 模块提供的方法
-
pickle.dump() 方法
pickle.dump()
方法用于将一个 Python 对象层次结构序列化为二进制字节流。该方法的原型如下
pickle.dump(obj, file, protocol = None, *, fix_imports = True)
此函数等效于
Pickler(file,protocol.dump(obj)
,用于将obj
序列化并将结果写入到file
文件对象。可选的
protocol
参数是一个整数,用于指定序列化过程时使用的协议版本号。支持的协议范围为0
到HIGHEST_PROTOCOL
。如果未指定该参数,则默认为DEFAULT_PROTOCOL
。如果指定了负数,则会自动设置为HIGHEST_PROTOCOL
。如果
fix_imports
参数设置为true
且protocol
小于 3,则序列化时将尝试将新的 Python3 名称映射到 Python2 中使用的旧模块名称,以便使用 Python2 可读取序列化后的数据流。我们写一段代码演示下
pickle.dump()
方法的使用import pickle import io class SimpleObject(object): def __init__(self, name): self.name = name l = list(name) l.reverse() self.name_backwards = ''.join(l) return data = [] data.append(SimpleObject('pickle')) data.append(SimpleObject('cPickle')) data.append(SimpleObject('last')) # 使用 BytesIO 模拟一个文件 out_s = io.BytesIO() # 将数据写入到流 for o in data: print('WRITING: %s (%s)' % (o.name, o.name_backwards)) pickle.dump(o, out_s) out_s.flush()
运行结果如下
[yufei@www.twle.cn java]$ python3 demo.py WRITING: pickle (elkcip) WRITING: cPickle (elkciPc) WRITING: last (tsal)
-
pickle.dumps() 方法
pickle.dumps()
方法用于将一个 Python 对象层次结构序列化为二进制字节流并返回序列化后的结果。该方法的原型如下
pickle.dumps(obj, protocol = None, *, fix_imports = True)
从方法原型中可以看出,参数和
pickle.dump()
方法几乎一样,因此我们就不做过多解释了。直接上范例import pickle data = [ { 'a':'A', 'b':2, 'c':3.0 } ] data_string = pickle.dumps(data) print ('PICKLE:', data_string)
运行结果如下
[yufei@www.twle.cn java]$ python3 demo.py PICKLE: b'\x80\x03]q\x00}q\x01(X\x01\x00\x00\x00aq\x02X\x01\x00\x00\x00Aq\x03X\x01\x00\x00\x00bq\x04K\x02X\x01\x00\x00\x00cq\x05G@\x08\x00\x00\x00\x00\x00\x00ua.
-
pickle.load() 方法
pickle.load()
方法用于从打开的文件对象文件中读取 pickle 序列化后的二进制数据流,并反序列化为一个 Python 3 对象层次结构该方法的原型如下
pickle.load(file, *, fix_imports = True, encoding = "ASCII", errors = "strict")
该方法和
Unpickler(file).load()
方法是等价的。同样的,参数也简单明了,我们不做过多介绍,直接看范例就好
import pickle import io class SimpleObject(object): def __init__(self, name): self.name = name l = list(name) l.reverse() self.name_backwards = ''.join(l) return data = [] data.append(SimpleObject('pickle')) data.append(SimpleObject('cPickle')) data.append(SimpleObject('last')) out_s = io.BytesIO() # Write to the stream for o in data: print('WRITING: %s (%s)' % (o.name, o.name_backwards)) pickle.dump(o, out_s) out_s.flush() # Set up a read-able stream in_s = io.BytesIO(out_s.getvalue()) # Read the data while True: try: o = pickle.load(in_s) except EOFError: break else: print('READ: %s (%s)' % (o.name, o.name_backwards))
运行结果如下
[yufei@www.twle.cn java]$ python3 demo.py WRITING: pickle (elkcip) WRITING: cPickle (elkciPc) WRITING: last (tsal) READ: pickle (elkcip) READ: cPickle (elkciPc) READ: last (tsal)
-
pickle.loads() 方法
pickle.loads()
方法用于从二进制数据流中读取 pickle 序列化后的二进制数据流,并反序列化为一个 Python 3 对象层次结构该方法的原型如下
pickle.loads(bytes_object, *, fix_imports = True, encoding = "ASCII", errors = "strict")
该方法和
pickle.load()
方法类似,区别在于一个从文件对象中读取数据,一个从二进制数据流中读取数据。我们写一段代码演示下这个方法的使用
import pickle import pprint data1 = [ { 'a':'A', 'b':2, 'c':3.0 } ] print('BEFORE:'), pprint.pprint(data1) data1_string = pickle.dumps(data1) data2 = pickle.loads(data1_string) print('AFTER:'), pprint.pprint(data2) print('SAME?:', (data1 is data2)) print('EQUAL?:', (data1 == data2))
运行结果如下
[yufei@www.twle.cn java]$ python3 demo.py BEFORE: [{'a': 'A', 'b': 2, 'c': 3.0}] AFTER: [{'a': 'A', 'b': 2, 'c': 3.0}] SAME?: False EQUAL?: True