1.学前一问:为什么需要序列化和反序列化这一操作呢?
- 便于存储。序列化过程将文本信息转变为二进制数据流。这样就信息就容易存储在硬盘之中,当需要读取文件的时候,从硬盘中读取数据,然后再将其反序列化便可以得到原始的数据。在Python程序运行中得到了一些字符串、列表、字典等数据,想要长久的保存下来,方便以后使用,而不是简单的放入内存中关机断电就丢失数据。python模块大全中的Pickle模块就派上用场了,它可以将对象转换为一种可以传输或存储的格式。
- 便于传输。当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把這个对象转换为字节序列,在能在网络上传输;接收方则需要把字节序列在恢复为对象。
2.pickle库基本介绍
pickle
是python语言的一个标准模块,安装python后已包含pickle
库,不需要单独再安装。
pickle
模块实现了基本的数据序列化和反序列化
。通过pickle
模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;通过pickle
模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。
在官方的介绍中,序列化操作的英文描述有好几个单词,如”serializing”, “pickling”, “serialization”, “marshalling” 或者”flattening”等,它们都代表的是序列化的意思。相应的,反序列化操作的英文单词也有好多个,如”de-serializing”, “unpickling”, “deserailization”等。为了避免混淆,一般用pickling
/unpickling
, 或者serialization
/deserailization
。
pickle模块是以二进制的形式序列化后保存到文件中(保存文件的后缀为.pkl
),不能直接打开进行预览。而python的另一个序列化标准模块json
,则是human-readable的,可以直接打开查看(例如在notepad++中查看)。
pickle
模块有两类主要的接口,即序列化和反序列化。
- 序列化
pickle.dump() Pickler(file, protocol).dump(obj)
- 反序列化
pickle.dump() Pickler(file, protocol).dump(obj)
3.序列化操作
3.1序列化方法pickle.dump()
pickle.dump(obj, file, protocol=None,*,fix_imports=True)
该方法实现的是将序列化后的对象obj以二进制形式写入文件file中,进行保存。它的功能等同于 Pickler(file, protocol).dump(obj)
。
参数obj
,要序列化的对象。
参数file
,有一点需要注意,必须是以二进制的形式进行操作(写入)。
with open('xxx.pkl', 'wb') as file:
参数protocol
,一共有5中不同的类型,即(0,1,2,3,4)。
- (0,1,2)对应的是python早期的版本-
- (3,4)则是在python3之后的版本。
- 参数可选
pickle.HIGHEST_PROTOCOL
和pickle.DEFAULT_PROTOCOL
。当protocol
参数为负数时,表示选择的参数是pickle.HIGHEST_PROTOCOL
。
官方文档说明:
Protocol version 0 is the original “human-readable” protocol and is backwards compatible with earlier versions of Python.
Protocol version 1 is an old binary format which is also compatible with earlier versions of Python.
Protocol version 2 was introduced in Python 2.3. It provides much more efficient pickling of new-style classes. Refer to PEP 307 for information about improvements brought by protocol 2.
Protocol version 3 was added in Python 3.0. It has explicit support for bytes objects and cannot be unpickled by Python 2.x. This was the default protocol in Python 3.0–3.7.
Protocol version 4 was added in Python 3.4. It adds support for very large objects, pickling more kinds of objects, and some data format optimizations. It is the default protocol starting with Python 3.8. Refer to PEP 3154 for information about improvements brought by protocol 4.
Protocol version 5 was added in Python 3.8. It adds support for out-of-band data and speedup for in-band data. Refer to PEP 574 for information about improvements brought by protocol 5.
3.2序列化方法pickle.dumps()
pickle.dumps(obj, protocol=None,*,fix_imports=True)
pickle.dumps()
方法跟pickle.dump()
方法的区别在于,pickle.dumps()
方法不需要写入文件中,它是直接返回一个序列化的bytes对象
。
3.3序列化方法Pickler(file, protocol).dump(obj)
pickle模块提供了序列化的面向对象的类方法,即
class pickle.Pickler(file, protocol=None,*,fix_imports=True)
Pickler
类有dump()
方法。
Pickler(file, protocol).dump(obj)
实现的功能跟 pickle.dump()
是一样的。
4.反序列化操作
4.1反序列化方法pickle.load()
pickle.load(file, *,fix_imports=True, encoding=”ASCII”. errors=”strict”)
该方法实现的是将序列化的对象从文件file中读取出来。它的功能等同于 Unpickler(file).load()
。
参数file
,有一点需要注意,必须是以二进制的形式进行操作(读取)。
with open('***.pkl', 'rb') as f:
4.2 反序列化方法pickle.loads()
pickle.loads(bytes_object, *,fix_imports=True, encoding=”ASCII”. errors=”strict”)
pickle.loads()
方法跟pickle.load()
方法的区别在于,pickle.loads()
方法是直接从bytes对象中读取序列化的信息,而非从文件中读取。
4.3 反序列化方法Unpickler(file).load()
pickle模块提供了反序列化的面向对象的类方法,即
class pickle.Unpickler(file, *,fix_imports=True, encoding="ASCII". errors="strict")
Unpickler
类有load()
方法。
Unpickler(file).load()
实现的功能跟 pickle.load()
是一样的。
5.哪些类型可以被序列化?
参考官方文档
The following types can be pickled:
None, True, and False; integers, floating-point numbers, complex numbers; strings, bytes, bytearrays; tuples, lists, sets, and dictionaries containing only picklable objects; functions (built-in and user-defined) defined at the top level of a module (using def, not lambda); classes defined at the top level of a module; instances of such classes whose __dict__ or the result of calling __getstate__() is picklable (see section Pickling Class Instances for details).