python的序列化和反序列化_Python-序列化和反序列化

为什么要序列化和反序列化

内存中的字典、列表、集合及其各种对象,如果保存到一个文件中?

如果自己定义类的实例,如何保存到一个文件中?

如果从文件中读取数据,并让他们在内存中再次恢复成自己对应的类的实例?

要设计一套协议,按照某种规则,把内存中数据保存到文件中,文件是一个字节序列,所以必须把数据转换成字节序,输出到文件,这就是序列化

反之,从文件的字节序列恢复到内存并且还是原来的类型,就是反序列化

定义

serialization 序列化

将内存中对象存储下来,把它变成一个个字节。->二进制

deserialization 反序列化

将文件的一个个字节序恢复成内存中对象。

序列化保存到文件就是持久化,可以将数据序列化后持久化,或者网络传输;也可以将文件从文件中或网络接收到的字节序反序列化。

Python提供了pickle库

pickle库

Python序列化和反序列化模块

函数      说明

dumps     对象序列化为bytes对象

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

loads          从bytes对象反序列化

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

importpickle

filename= '/tmp/ser.bin'i= 99c= 'c'l= list('123')

d= {'a':1,'b':'abc','c':[1,2,3]}#序列化

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(),f.seek(0))for i in range(4):

x=pickle.load(f)print(i+1,x,type(x))

输出

b'\x80\x03Kc.\x80\x03X\x01\x00\x00\x00cq\x00.\x80\x03]q\x00(X\x01\x00\x00\x001q\x01X\x01\x00\x00\x002q\x02X\x01\x00\x00\x003q\x03e.\x80\x03}q\x00(X\x01\x00\x00\x00aq\x01K\x01X\x01\x00\x00\x00bq\x02X\x03\x00\x00\x00abcq\x03X\x01\x00\x00\x00cq\x04]q\x05(K\x01K\x02K\x03eu.'01 99

2 c

3 ['1', '2', '3']

4 {'a': 1, 'b': 'abc', 'c': [1, 2, 3]}

示例中保存了一个类名,因为所有的其他东西是类定义的东西,是不变的,所以只序列化一个AAA类名,反序列化的时候找到类就可以恢复一个对象

importpickleclassAAA:

t= 'ABC'

defshow(self):print('abc')

a1=AAA()

ser=pickle.dumps(a1)print('ser={}'.format(ser))#输出

ser=b'\x80\x03c__main__\nAAA\nq\x00)\x81q\x01.'

a2 = pickle.loads(ser)

print(a2.t)

print(a2.show)

从示例中可以看出,这回除了AAA必须保存外,还序列化了aaaa和abc,因为这是每一个对象自己的属性,每一个对象不一样,所以这些数据需要序列化

importpickleclassAAA:def __init__(self):

self.aaaa= 'abc's1=AAA()

ser=pickle.dumps(s1)print('ser={}'.format(ser))

s2=pickle.loads(ser)print(s2,type(s2))print(s2.aaaa)print(id(s1),id(s2))#输出

ser=b'\x80\x03c__main__\nAAA\nq\x00)\x81q\x01}q\x02X\x04\x00\x00\x00aaaaq\x03X\x03\x00\x00\x00abcq\x04sb.'

<__main__.aaa object at> abc140585946837120 140585947363256

序列化、反序列化实验

定义类AAA,并序列化到文件

importpickleclassAAA:def __init__(self):

self.aaaa= 'abc'a1=AAA()

ser=pickle.dumps(a1)print('ser={}'.format(ser))print(len(ser))

filename= '/tmp/ser.bin'with open(filename,'wb') as f:

pickle.dump(a1,f)

将产生的文件ser.bin发送到其他节点上,增加一个xxx.py文件执行python3 xxx.py

会抛出异常信息,这个异常实际上是找不到类AAA,增加类定义即可解决

反序列化的时候要找到AAA类的定义,才能成功,否则会抛出异常

importpickle

with open('/tmp/ser.bin','rb') as f:

a=pickle.load(f)#AttributeError: Can't get attribute 'AAA' on

序列化应用

一般来说,本地序列化的情况,应用较少,大多数场景应用在网络中

将数据序列化后通过网络传输到远程节点,远程服务器上的服务接收到数据反序列化后就可以用了,但是要注意一点,远程接收端,发序列化时必须有对应的数据类型,否则会抛异常,尤其是自定义类,远程得有一致的定义。

现在大多数项目都不是单机应用,需要多个程序之间配合,需要通过网络将数据传输到其他节点上,这就需要大量的序列化和反序列化的过程。

但是问题来了,Python程序之间可以都使用pickle解决序列化和反序列化,如果跨平台、跨语言、跨协议pickle就不太合适,就需要使用到公共的协议,例如xml/json/Protocol Buffer等。

不同协议效率不同,使用场景要根据不同的情况分析选型。

JSON(文本序列化方案,推荐使用)

JSON是一种轻量级的数据交换格式,它是基于ECMSCRIPT的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。

值:双引号引起来的字符串、数值、true/fase/null、对象、数组,这些都是值

字符串

由双引号包围起来的任意字符的组合,可以有转义字符

数值

有正负、有整数、有浮点数

对象

示例:

{"person":[

{"name": "tom","aget": 18},

{"name": "tom","aget": 18}

],"total": 2}

json模块

Python与json

Python支持少量的内建数据类型到json类型的转换。

常用的方法:

Python类型      Json类型

dumps        json编码

dump          json编码并写入文件

loads           json解码

load          json解码,并从文件中读取数据

importjson

d= {'name':'tom','age':20,'id':123,'a':['b','c']}

j=json.dumps(d)print(j)print(type(j))print('----------------------------------------------')#反序列化

d =json.loads(j)print(d,type(d))#输出

{"name": "tom", "age": 20, "id": 123, "a": ["b", "c"]}

----------------------------------------------{'name': 'tom', 'age': 20, 'id': 123, 'a': ['b', 'c']}

一般json编码的数据很少落地,数据都是通过网络传输, 传输的时候要考虑压缩它,本质上来说就是文本,就是说字符串。

json很简单,几乎编程语言都支持json,应用范围比价广泛。

MessagePack

MessagePack是一个基于二进制高效的对象序列化类库,可以用于跨语言通信,它可以像json那样,在许多种语言之间交换结构对象,但是它比json更为轻巧,支持Python、Java、c/c++等众多语言

安装:

pip install msgpack

importjsonimportpickleimportmsgpack

d= {'name':'tom','age':20,'id':123,'a':['b','c']}

tmp=pickle.dumps(d)print(len(tmp)) #81 bytes

j=json.dumps(d)print(len(j)) #54 bytes

m=msgpack.dumps(d)print(len(m)) #26

MessagePack简单易用,高效压缩,支持语言丰富,所以,用它序列化也是一种很好的选择,上诉示例中pickle比json序列化的结果还要大,原因在于pickle要解决所有Python类型数据的序列化,要记录各种数据类型包括自定义类,而json只需要支持少数几种类型,所以简单,都不需要类型的描述,而大多数情况下我们序列化都是处理这些简单的类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值