当程序运行起来时(也就是进程),所有的变量都保存在内存中, 当进程结束后,该进程申请的内存都要被操作系统回收,我们在内存中的数据就会丢失, 如果想使数据持久化,我们可以把数据存储在磁盘上。 但是文件对象只能处理字符流,如果我们要存储的数据类型为其它类型(int,float,bool,list,tuple,dict等等)应该怎么办呢。
不但读写磁盘需要通过文件对象,网络传输数据也需要通过文件对象,因为网络 IO 是指通过文件对象是读写网卡而已,磁盘 IO 是指通过文件对象读写磁盘而已。我们知道文件对象只能处理字符流,如果我们想把非字符类型(int,float,bool,list,tuple,dict等等)的数据通过网络发送到其它机器上应该怎么办呢。
根据以上两个问题,我们本节课就来学习一下序列化:我们把变量从内存中变成可存储或传输的过程(也就是变成字符流的过程),称之为序列化,序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。 反之,能把序列化后的字符流还原成序列化之前的类型数据的过程叫反序列化。
pickle 模块
在 Python 中有两个模块可以对数据进行序列化和反序列化:cPickle 和 pickle。这两个模块功能是一样的,区别在于 cPickle 是 C 语言写的,速度快;pickle 是纯 Python 写的,速度慢。我们用的时候可以先尝试导入 cPickle,如果失败,再导入 pickle。
try:
import cPickle as pickle
except ImportError:
import pickle
mylist = [1, True, "hello"]
seqdata = pickle.dumps(mylist) # 序列化成字符流
print(type(seqdata)) # list 类型数据 序列化成 str 类型
print(seqdata) # 序列化后的字符流
mylistreseq = pickle.loads(seqdata) # 把被序列化的字符流反序列化成 list
print(type(mylistreseq)) # list 类型
print(mylistreseq) # 反序列化后的 list
我们可以把 Python 内置的各种类型的数据序列化成字符流数据,然后用文件对象存储到磁盘上。 同样,我们也可以用文件对象读出这些序列化后的字符流,然后反序列化成它原来的类型数据到内存中。 注意:在 Python 3 中,把用 pickle 序列化后的字符流存储到磁盘,必须以 wb 的形式;同样,从磁盘上读取用 pickle 序列化后的字符流用 rb 的形式。
try:
import cPickle as pickle
except ImportError:
import pickle
mylist = [1, True, ("hello", None)]
f = open("d:/test.txt", "wb")
seqdata = pickle.dumps(mylist) # 序列化成字符流
f.write(seqdata)
f.close()
f = open("d:/test.txt", "rb")
seqdata = f.read()
f.close()
mylistreseq = pickle.loads(seqdata) # 反序列化后的 list
print(mylistreseq)
对于我们自定义类型,同样