一 概述

1 为什么要序列化

因为TCP/IP协议只支持字节数组的传输,不能直接传对象。对象序列化的结果一定是字节数组!当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。

2 序列化和反序列化

序列化(serialization):及有序的列,数据转换成二进制的有序的过程
协议:规定序列化和反序列化的转换方式及就是把数据保存成二进制存储起来,其是定义的规则,其规则称为协议如果规定了协议,则可以进行序列化和反序列化,其协议是由版本的,约定协议后进行处理

反序列化(deserialization):将有序的二进制序列转换成某种对象(字典,列表等)称为反序列化

持久化:序列化保存到文件就是持久化,序列化未必会持久化,序列化往往是传输或存储。可以将数据序列化后持久化,或者网络传输,也可以将从文件或网络接受到的字节序列反序列化。

二 python pickle

1 概述

pickle python中的序列化,反序列化模块,其局限是仅限于传输的两端都是python的情况,且尽量保持两端的版本一致

2 pickle 库基本方法

dumps 对象序列化,在内存中
dump 对象序列化到文件对象,就是存入文件
loads 对象反序列化
load 对象反序列化,从文件中读取数据

3 实例

#!/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))

结果如下

python 序列化和反序列化

#!/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))  # 进行反序列化并输出

结果如下
python 序列化和反序列化

切换3.5环境进行查看处理
python 序列化和反序列化

对类的处理

#!/usr/local/bin/python3.6
#coding:utf-8
from  pickle import  *
from  pathlib  import Path
class  A():  #创建一个类
    def show(self):
        print ('aaaa')
a=A()  # 对类进行实例化
with  open('/root/test1.py','wb+')  as  f:  # 将实例化后的类的对象使用序列化写入到文件中
    dump(a,f)
with  open('/root/test1.py','rb')  as  f: # 将对象的结果进行查看
    x=load(f)
    x.show()

结果如下

python 序列化和反序列化

python 序列化和反序列化

#!/usr/local/bin/python3.6
#coding:utf-8
from  pickle import  *
from  pathlib  import Path
class  A():  #创建一个类
    def show(self):
        print ('aaaa')
        print  ('bbbbb')
a=A()  # 对类进行实例化
with  open('/root/test1.py','wb+')  as  f:  # 将实例化后的类的对象使用序列化写入到文件中
    dump(a,f)
with  open('/root/test1.py','rb')  as  f: # 将对象的结果进行查看
    x=load(f)
    x.show()  # 调用类的方法

查看结果
python 序列化和反序列化
写入的数据如下
python 序列化和反序列化

此处写入的数据未发生改变,但其在类中增加了数据,此处记录的是模块名和类名。若在不同的平台进行操作,则会报错

切换3.5环境,报错,因为其中没有这个test的模块名没有对应的classA,因此会报错。

python 序列化和反序列化

对象序列化

#!/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)  # 调用类的方法

查看如下
python 序列化和反序列化
查看写入数据,其发生了变化

python 序列化和反序列化
但其切换环境,还是不能找到
python 序列化和反序列化

4 总结

RPC 雏形:
远程过程调用: 及远程调用某个模块的函数来实现其过程的调用 ,必须要保证远程的函数和本地需要的函数一致并且必须存在,否则会报错
通过网络传输,不需要持久化,进行类的一致性
对于非自定义类,两边一致,不需要,若是自定义类,则需要两端保持一致


应用:
本地序列化的情况,应用较少
一般来说,大多数应用场景在网络中,将数据序列化后通过网络传输到远程结点,远程服务器上的服务接受到数据后进行反序列化,就可以使用了。
但是,需要注意的是,远端接受端,反序列化时必须有对应的数据类型,否则就会报错,尤其是自定义类,必须远程存在


目前,大多数项目都不是单机,不是单服务,需要通过网络将数据传送到其他结点上,这就需要大量的序列化,反序列化。
但是python程序之间还可以使用pickple解决序列化,反序列化,如果是跨平台,跨语言,跨协议pickle就不适合了,就需要公共协议,如XML/Json /protocol Buffer等。
每种协议都有自己的负载,其所使用的场景都不一样,二进制的操作不一定适用于所有的场景。但越是底层的协议,越需要二进制传输

三 JSON

1 概述

JSON(JavaScript object notation,JS 对象标记)是一种轻量级的数据交换格式,它基于ECMAscript(w3c制定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据

2 JSON的数据类型

其key必须是字符串,其值可以是下面类型

双引号引起来的字符串,数值,true和false,null(None),对象(字典),数组(列表)这些都是值

python 序列化和反序列化
此处表示了JSON值支持的数据类型

1 string:

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


2 number :
数值,有正负数,整数,浮点数


3 对象:
无序的键值对集合
格式:{key1:value1,...keyn:valuen}
key 必须是字符串,需要使用双引号包围这个字符串,value可以是任意合法的值

python 序列化和反序列化

其表示要么是{},要么有key,value,若key:value完成,则后面不能有逗号,一旦有逗号,则表示后面还有数据


4 数组 :
python 序列化和反序列化

同上,一旦有逗号,则表示后面还有数据

python 序列化和反序列化

此处的问题是,其json文件的键是非字符串,其值的字符串不是使用双引号括起来的,因此其会出现报错的情况


5 null 相当于python的None


6 布尔型 false(False) true(True)

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))))  # 对结果进行反序列化

结果如下
python 序列化和反序列化

#!/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())))  # 对其进行反序列化

结果如下
python 序列化和反序列化

一般的json编码的数据很少落地,数据都是通过网络传输,传输的时候,要考虑压缩它,本质上来说它就是一个文本,一个字符串,json很广泛,几乎所有的编程语言都支持它。

四 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'))  #通过制定编码方式输出

结果如下
python 序列化和反序列化