序列化和反序列化

目录结构

  1. 序列化:按照某种规则,把内存中数据保存到文件中。
  • 文件时一个字节序列,所以必须把数据转换成字节序列,输出到文件。
  1. 反序列化:从文件的字节序列恢复到内存并且还原原来的类型。

定义

  • serialization 序列化,将内存中对象存储下来,把他变成一个个字节。->二进制
  • deserialization 反序列化,将文件的一个个字节恢复成内存中对象。->二进制
    序列化保存到文件就是持久化,可以将数据序列化(持久化)后用于网络传输;也可以将从文件中或者网络接受到的字节序列反序列化。
  • Python中pickle库就是用来序列化和反序列化的。

pickle库

函数

说明

dumps

对象序列化为bytes对象

dump

对象序列化到文件对象,就是存入文件

loads

从bytes对象反序列化

load

对象反序列化,从文件读取数据

  • dump(obj,file,protocol=None,*,fix_imports=True) #将obj对象序列化后写入file中
  • obj:需要序列化的对象
  • file:文件描述符,需要写入的文件描述符
  • protocol:协议
  • fix_imports:
  • dumps(obj, protocol=None, *, fix_imports=True)->bytes #将obj对象序列化后返回序列化的bytes对象
  • obj:需要序列化的对象
  • protocol:协议
  • fix_imports:
  • bytes:返回值 序列化后的bytes
  • load(file, *, fix_imports=True, encoding=“ASCII”, errors=“strict”) #从文件中读取内容反序列化。
  • file :文件描述符,序列化后生成的文件。
  • fix_imports:
  • encoding:文件编码,默认为ASCII
  • errors
  • loads(bytes_object, *, fix_imports=True, encoding=“ASCII”, errors=“strict”)->从bytes中反序列化
  • bytes_object:序列化后的bytes对象
  • fix_imports:
  • encoding:编码
  • errors

简单综合示例

import pickle
i = 99
c = 'c'
l = list('123')
d = {"a":1,"b":"abc","c":[1,2,3]}

filename = "xddpython"
#序列化
with open(filename,'wb') as f:
pickle.dump(i,f)
pickle.dump(c,f)
pickle.dump(l,f)
pickle.dump(d,f)
#读取序列化后生成的文件
with open(filename,"rb") as f:
print(f.read())

#反序列化
with open(filename,"rb") as f:
while 1:
try:
x = pickle.load(f)
except Exception:
break;
print(x)

输出结果为:

序列化和反序列化pickle_序列化和反序列化

类的序列化和反序列化

Python中的pickle模块,对类的序列化。记录了类名,方法名。以及类的属性。不会记录类中方法的执行代码。所以如果对同一个类序列化后。在改变类中的方法,然后将序列化的文件反序列化生成类,那么生成的类中会使用修改后的方法。

  • 简单示例
import pickle
class AAA:
ttt = "ABC"
def show(self):
print('abc')
#创建AAA对象
a1 = AAA()
print("序列化前:")
print("ttt = ",a1.ttt)
print("show()\t",a1.show())
#序列化
ser = pickle.dumps(a1)
#重新定义类AAA
class AAA:
ttt = "BBB"
def show(self):
print('def')
a2 = pickle.loads(ser)
print("反序列化后:")
print("ttt = ",a2.ttt)
print("show()\t",a2.show())

输出结果为:

序列化和反序列化pickle_python中的pickle模块_02

  • 注意:如果类中定义了属性,那么属性和属性值会被记录在序列化生成的bytes中。应为这是每一个对象自己的属性,同一个对象都有自己不同属性值。所有这些数据需要序列化到bytes中。
    简单示例:
import pickle
class AAA:
def __init__(self):
self.aaaa = "abc"
a1 = AAA()
print("序列化前aaaa属性:",a1.aaaa)
#序列化
ser = pickle.dumps(a1)
#重新定义类
class AAA:
def __init__(self):
self.aaaa = "def"
#反序列化
a2 = pickle.loads(ser)
print("反序列化后aaaa属性:",a2.aaaa)

输出结果为(可以看到属性值并没有改变):

序列化和反序列化pickle_序列化_03

总结

  1. 注意对类的反序列化,运行环境中必须要有反序列化中记录的类的对象。如果没有无法反序列化,会出现AttributeError异常。
  2. 对于类的序列化,序列化的bytes中会记录类名,以及方法名,和类的属性名和属性值。
  3. 序列化和反序列化必须保证使用同一套类的定义,否则会带来不可预料的结果。

序列化的应用

  • 一般类似,本地序列化的情况,应用较少。大多数场景都应用在网络传输中。将数据序列化后通过网络传输远程结点,远程服务器上的服务将接受到数据反序列化后,就可以使用了。但是,要注意一点:远程接收端,反序列化时必须有对应的数据类型,否则会报错。尤其是自定义类,必须远程端有一致的定义。
  • 现在大多数项目都不说单机的。也不是单服务。需要多个程序之间配合。需要通过网络将数据传送到其他节点上去,这就需要大量的序列化、反序列化过程。
  • Python程序之间还可以使用pickle解决序列化、反序列化,如果是跨平台、跨语言、跨协议pickle就不太适合,就需要用到公共的协议。例如:XML,Json,Protocol Buffer等。不同的协议,效率不同、学习曲线不同,适合不同场景,要根据不同的情况分析选型。