python 序列化和反序列化
一 概述
1. 什么是序列化
因为TCP/IP协议只支持字节数组的传输,不能直接传对象。对象序列化的结果一定是字节数组!当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。
2. 序列化和反序列化
协议:规定序列化和反序列化的转换方式及就是把数据保存成二进制存储起来,其是定义的规则,其规则称为协议如果规定了协议,则可以进行序列化和反序列化,其协议是由版本的,约定协议后进行处理
序列化(serialization):及有序的列,数据转换成二进制的有序的过程
反序列化(deserialization):将有序的二进制序列转换成某种对象(字典,列表等)称为反序列化
持久化:序列化保存到文件就是持久化,序列化未必会持久化,序列化往往是传输或存储。可以将数据序列化后持久化,或者网络传输,也可以将从文件或网络接受到的字节序列反序列化。
二 python pickle
1. 概述
python pickle 中的序列化,反序列化模块,其局限是仅限于传输的两端都是python的情况,且尽量保持两端的版本一致
2 . pickle库基本方法
dumps 对象序列化,在内存中
dump 对象序列化到文件对象,就是存入文件
loads 对象反序列化
load 对象的反序列化,从文件中读取数据
3. 实例
dump/load
#!/usr/local/bin/python3.6
#coding:utf-8
from pickle import *
from pathlib import Path
lst='a b c d'.split() #返回一个列表
d=dict(zip('abcd',range(4))) #构建一个字典
print (lst,d) # 打印字典和列表
p=Path('/root/test.py')
if not p.parent.exists(): # 创建文件的上级目录
p.parent.mkdir(parents=True)
with open(p,'wb+') as f: #进行序列化,必须是二进制的输入,否则会报错
dump(lst,f)
dump(d,f)
with open(p,'rb') as f: #此处对应的是二进制的输出
print (load(f))
print (load(f))
[‘a’, ‘b’, ‘c’, ‘d’] {‘a’: 0, ‘b’: 1, ‘c’: 2, ‘d’: 3}
[‘a’, ‘b’, ‘c’, ‘d’]
{‘a’: 0, ‘b’: 1, ‘c’: 2, ‘d’: 3}
dumps / loads
#!/usr/local/bin/python3.6
#coding:utf-8
from pickle import *
from pathlib import Path
d=dict(zip('mysql',range(5)))
s=dumps(d) #进行序列化
print (s) # 正常情况的输出
print (loads(s)) # 进行反序列化并输出
b’\x80\x03}q\x00(X\x01\x00\x00\x00mq\x01K\x00X\x01\x00\x00\x00yq\x02K\x01X\x01\x00\x00\x00sq\x03K\x02X\x01\x00\x00\x00qq\x04K\x03X\x01\x00\x00\x00lq\x05K\x04u.’
{‘m’: 0, ‘y’: 1, ‘s’: 2, ‘q’: 3, ‘l’: 4}
对类的处理
from pickle import *
from pathlib import Path
class A(): # 创建一个类
def show(self):
print('aaaa')
a = A() # 对类进行实例化
with open('./牛客网/test1.py', 'wb+') as f: # 将实例化后的类的对象使用序列化写入到文件中
dump(a, f)
with open('./牛客网/test1.py', 'rb') as f: # 将对象的结果进行查看
x = load(f)
x.show()
aaaa
对象序列化
#!/usr/local/bin/python3.6
#coding:utf-8
from pickle import *
from pathlib import Path
class A(): #创建一个类
def __init__(self): #对类进行初始化的操作,及就是在对象赋值时,此类会被带入其中
self.tttt='abcdf'
a=A() # 对类进行实例化
with open('/root/test1.py','wb+') as f: # 将实例化后的类的对象使用序列化写入到文件中
dump(a,f)
with open('/root/test1.py','rb') as f: # 将对象的结果进行查看
x=load(f)
print (x.tttt) # 调用类的方法
abcdf
应用:
本地序列化的情况,应用较少
一般来说,大多数应用场景在网络中,将数据序列化后通过网络传输到远程结点,远程服务器上的服务接受到数据后进行反序列化,就可以使用了。
但是,需要注意的是,远端接受端,反序列化时必须有对应的数据类型,否则就会报错,尤其是自定义类,必须远程存在
目前,大多数项目都不是单机,不是单服务,需要通过网络将数据传送到其他结点上,这就需要大量的序列化,反序列化。
但是python程序之间还可以使用pickple解决序列化,反序列化,如果是跨平台,跨语言,跨协议pickle就不适合了,就需要公共协议,如XML/Json /protocol Buffer等。
每种协议都有自己的负载,其所使用的场景都不一样,二进制的操作不一定适用于所有的场景。但越是底层的协议,越需要二进制传输
三 JSON
1. 概述
JSON(JavaScript object notation,JS 对象标记)是一种轻量级的数据交换格式,它基于ECMAscript(w3c制定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据
2. JSON的数据类型
其 key必须是字符串,其值可以是下面类型
双引号引起来的字符串,数值,true和false,null(None),对象(字典),数组(列表)这些都是值
3. 常用方法
dumps json 编码
dump json 编码并存入文件
loads json 解码
load json 解码,从文件读取数据
4. 应用
'''对数据进行操作'''
#!/usr/local/bin/python3.6
#coding:utf-8
from json import *
d={'a':1,'b':{'c':{'d':[1,23,4,5]}},'e':None,'f':True,'g':False} #构造字典
print (d) # 输出字典
print (dumps(d)) #对字典对象进行序列化
print (loads((dumps(d)))) # 对结果进行反序列化
'''对类的操作'''
#!/usr/local/bin/python3.6
#coding:utf-8
from json import *
class A(): # 创建一个类
def show(self):
return 'mysql'
print (dumps(A().show())) # 对类进行实例化并调用其方法返回结果进行序列化
print (loads(dumps(A().show()))) # 对其进行反序列化
‘mysql’
mysql
四 messagepack(第三方库)
1. 概述
messagepack 是一个基于二进制高效的对象序列化类库,可用于跨语言通信,其可以像JSON那样,在许多语言之间交换结构对象,但是其比JSON更快速更轻巧。其支持python,ruby,Java,C/C++等众多语言,兼容JSON和pickle
2. 安装
pip install msgpack-python
3. 常用方法
packb 序列化对象,提供了dumps来兼容pickle和json
unpackb 反序列化对象,提供了loads来兼容pack序列化对象保存到文件对象,提供了dump来兼容
unpack 反序列化对象保存到文件对象,提供了load来兼容
4. 基本应用
#!/usr/local/bin/python3.6
#coding:utf-8
from msgpack import *
import sys
d={'a':1234,'b':['abc',{'c':234}],'d':True,'e':False,'f':None} # 构建一个字典
b=packb(d) # 进行序列化操作
print (b) # 打印
print (unpackb(b)) #进行反序列化操作
print (unpackb(b,encoding='utf-8')) #通过制定编码方式输出