在机器学习中,我们常常需要把训练好的模型存储起来,这样在进行使用时直接将模型读出,而不需要重新训练模型,这样就大大节约了时间。Python提供的pickle模块就很好地解决了这个问题,使用它可以轻松序列化对象并保存到磁盘中,并在需要的时候读取出来,任何对象都可以执行序列化操作。
pickle提供了一个简单的持久化功能。可以将对象以文件的形式存放在磁盘上。
有人不禁要问了,python已经提供了文件的读写功能了,为什么还要pickle模块呢?
其实python从一个文件中读取字符串是非常简单的,但是如果想要读取出数值,那就有点不简单了,python中日常读取文件的方法比如read()或者readline()都是返回一个字符串类型,想要取出数值的话,可以使用int函数或者float函数把类似’123’或者’2.7’这样的字符串强制转换为数值类型,这样就很麻烦了。
另外,保存文件,通过write方法写入文件并保存的文件都是字符串的形式,如果你要保存类似列表,字典甚至是类的实例这样的更为复杂的数据类型的时候,普通的文件操作就好像有点力不从心了。当然你也可以把这些都以字符串的形式保存在文件中,但是当你要使用它而去读取的时候,从文件中回复到原来的数据对象,就变得异常麻烦了!!!
Python提供的标准模块-pickle就提供了这样的功能,使用这个模块,可以很方便的把列表,字典,或者类对象这类复杂数据类型存储为文件,并且读取的时候能从文件中回复到原来的对象,而不丢失其身份和类型等信息。
另外,它存储的文件类型也和一般的不一样,是二进制文件,它几乎可以把所有的python对象都传化成二进制形式的文件,这个过程称为pickling,从二进制转换回对象的过程称为unpickling。
pickle模块有两类主要的接口,即序列化(dump)和反序列化(load)
序列化方法pickle.dump()
ickle.dump(obj, file, protocol=None,*,fix_imports=True)
该方法实现的是将序列化后的对象obj以二进制形式写入文件file中,进行保存。关于参数file,有一点需要注意,必须是以二进制的形式进行操作(写入),如下图:
把这个列表保存起来,一定要以二进制的文件形式打开文件,这里的后缀名可以是随意的,不一定非要是’pkl’,但是使用的是pickle保存的,为了方便识别,建议直接使用’.pkl’文件格式。完成后记得把打开的文件关闭(close),这个和普通的文本文件一样。
在当前目录下就生成了一个data.pkl文件,打开之后是乱码(因为这是二进制文件),如下图:
反序列化方法pickle.load()
该方法的相关参数如下:
pickle.load(file, *,fix_imports=True, encoding=“ASCII”. errors=“strict”)
该方法实现的是将序列化的对象从文件file中读取出来,关于参数file,有一点需要注意,必须是以二进制的形式进行操作(读取)
可以直接获取我们的列表了,如下图:
如果是天气或者地图坐标文件,使用这个模块简直不要太方便。
Pickle模块可以保持任何你能想到的东西!!
序列化反序列化的衍生方法
序列化方法pickle.dumps()
pickle.dumps(obj, protocol=None,*,fix_imports=True)
pickle.dumps()方法跟pickle.dump()方法的区别在于,pickle.dumps()方法不需要写入文件中,它是直接返回一个序列化的bytes对象。
反序列化方法pickle.loads()
pickle.loads(bytes_object, *,fix_imports=True, encoding=“ASCII”. errors=“strict”)
pickle.loads()方法跟pickle.load()方法的区别在于,pickle.loads()方法是直接从bytes对象中读取序列化的信息,而非从文件中读取。
为什么使用二进制文件格式?
便于存储。序列化过程将文本信息转变为二进制数据流。这样就信息就容易存储在硬盘之中,当需要读取文件的时候,从硬盘中读取数据,然后再将其反序列化便可以得到原始的数据。
便于传输。当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把這个对象转换为字节序列,在能在网络上传输;接收方则需要把字节序列在恢复为对象。
cPickle包
cPickle包的功能和用法与pickle包几乎完全相同 (其存在差别的地方实际上很少用到),不同在于cPickle是基于c语言编写的,速度是pickle包的1000倍,它具有更好的性能,对于大多数应用程序,推荐使用该模块。如果想使用cPickle包,我们都可以直接这样使用:import cPickle as pickle就可以了。