TOC

序列化简介

    序列化指的是将一个数据变为二进制的方式,那么反之,反序列化就是指的将一个二进制数据转为原始数据,我们写的东西起初都是放在内存中的,为了数据的安全性,我们需要将这个数据存储到文件当中持久化,那么内存中的结构可能非常复杂,但是我们得想办法将其存储在磁盘上,而且不断需要存储在磁盘上,下次在读取的时候,还能还原到内存原有的结构;
    在内存中的所有数据都是0和1,它本身是没有类型的,除了让计算机自己能够知道这个指定区域0和1该当成什么数据类型去理解,它才有意义,列表类型有列表类型的方法、集合类型有集合的方法,他们在内存中数据的存放格式和理解的数据格式是不一样的,关键是内存的这种数据结构是怎么存储到磁盘上去的,当需要使用的时候,又是如何将它还原回原来在内存中的样子;
    更何况啊,可能python对于一个[1,2,3]这样的序列称之为list,Java却把它理解为一个Arrary,它会在存储数据到内存中时会增加一些标识符来标识这些所属Python的东西,当然,这是Python解释器干的事,但是内存中的东西,包括字典怎么才能将他们变成字节序列,并且挨着个存到磁盘上去呢,这就是如何序列化的问题;
    假设我们打的是网络游戏,比如吃鸡,我们每次打游戏时的数据不是打完第二天就恢复原样了,那是因为数据起初都是存在网游所在机器的内存当中的,然后实时通过网络将数据传递给服务端,服务端也起初会放在内存当中,后面数据还是会持久化到磁盘上面来,所以也需要事先将其变成一个一个字节,然后将其写入到磁盘当中;
    上面说过,内存中的数据,如果我们保存下来,下次要使用的时候,还需要能够将其还原成原来的在内存中的格式,对变成语言来讲,设计了一套协议,按照某种规则,把内存中的数据保存到文件中,那么因为文件是一个字节序列,所以在保存之前还必须得事先将内存中的数据转为字节序列,然后再全部序列化下来,那么对于Python来讲,它也有序列化和反序列化的能力;

序列化和反序列化

    序列化,serialization,这个序列化就是将内存中的各种对象,比如int类型的、float类型的、string类型的、list类型的等,想办法把它变成一个一个的字节序列,然后当我们拿到这个字节序列的时候,就可以立即使用文件的二进制操作方式,将这个字节序列存储下来,此时我们可以选择网络发送到远端服务器,也可以选择写入文件,存储到本地文件上面来,这就是序列化的过程;
    说白了序列化就是将数据变成字节序列,那么至于序列化存不存储,那就是另一回事了,因为序列化之后可以通过网络发送给另一台服务器,所以序列化指的是,从内存对象到二进制序列的过程,持久化指的是,将程序给定的一个个字节序列,或者一个个文本序列存储到磁盘,这叫持久化的过程,掉电不丢失;
    反序列化,deserialization,从磁盘读或者从网络读,总之读取一个字节序列过来,如果要将其转为其原来在内存中的样子,这个时候就需要在这个读取过来的字节序列中指定,这个数据到底是字符还是int,还是其他数据类型,然后将其在内存中还原成原有的数据,这个一点我们称之为反序列化;
json
    一般来讲,本地序列化的情况比较少,大多数场景都是应用在网络传输中,将数据发往网络上的其他服务器上,那么在发送之前就需要进行序列化,数据到达服务器端还需要反序列化,但是需要注意一点,远端服务器反序列化时必须有对应的数据类型,否则就会报错,尤其上自定义类,必须在远端服务器有一致的定义;
    尤其是现在,大多数下面都已经面向微服务,需要多个程序之间配合,这些服务之间需要进行数据交互,这就需要大量使用序列化、反序列化过程,如果是python程序和python程序之间进行数据交互,这是没问题的,但是如果是python程序与java程序之间,这就有问题了;
    虽然说python和java都能够识别一些基本的类型,比如int、str,python程序和java程序之间是可以进行交互的,但是如果是自定义类型,那这个时候就有问题,可能在Python中一些自由的类型,恰好在Java中没有,那么将这个数据放在Java当中,就有问题了,Java程序是无法理解的;
    所以如果当遇到跨平台、跨语言、跨协议,就会产生一定的问题,所以这就需要公共协议了,例如XML、JSON、Protocol Buffer等,他们是一种通用型格式;
    JSON是JS中的一种对对象的文本描述,用文本的方式记录对象,也就是说字符串可以转为一个对象,是一种轻量级数据交换格式,它基于ECMAScript(W3C组织指定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据 ;
dump:用于将数据写入文件,需要传递两个参数,第一个参数是需要写入的数据,第二个参数是文件句柄;
load:用于读文件内容,只需要指定读取的文件句柄即可;
dumps:数据转换,将数据转换成json类型的字符串;
loads:数据转换,将json类型的字符串转换成原来的数据;
数据转换
    如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,JS原声支持,非常方便,JSON和Python内置的数据类型对应如下表;
Python
Json
dict
object
list、tuple
array
str、unicode
string
int、long、float
number
True
true
False
false
None
null
import json

userinfo = {'name': 'cce', 'age': 25, 'sex': 'm'}

# 将数据序列化成二进制
print(json.dumps(userinfo))  # {"age": 25, "name": "cce", "sex": "m"}
# 将二进制序列化数据反序列化成原始数据
print(json.loads(json.dumps(userinfo)))  # {'sex': 'm', 'name': 'cce', 'age': 25}

# 将数据序列化成二进制,并进行持久化
with open('data.json', 'w') as fp:
    json.dump(userinfo, fp)
# 将json数据反序列化
with open('data.json', 'r') as fp:
    print(json.load(fp)) # {'sex': 'm', 'name': 'cce', 'age': 25}
messagepack
   它是在Python很多基础库都应用的一种二进制序列化方案,是一个基于二进制高效的对象序列化类库,可用于跨语言通信。它可以像JSON那样,在许多种语言之间交换结构对象;但是它比JSON更快速也更轻巧。支持Python、Ruby、Java、C/C++等众多语言。比Google Protocol Buffers还要快4倍,常用方法和JSON一样;
import msgpack

userinfo = {'name': 'cce', 'age': 25, 'sex': 'm'}

# 将数据序列化成二进制
print(msgpack.dumps(userinfo))  # b'\x83\xa3sex\xa1m\xa4name\xa3cce\xa3age\x19'
# 将二进制序列化数据反序列化成原始数据
print(msgpack.loads(msgpack.dumps(userinfo)))  # {'sex': 'm', 'name': 'cce', 'age': 25}

# 将数据序列化成二进制,并进行持久化
with open('data.msg', 'wb') as fp:
    msgpack.dump(userinfo,fp)
# 将数据反序列化
with open('data.msg','rb') as fp:
    print(msgpack.load(fp)) # {'sex': 'm', 'name': 'cce', 'age': 25}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注