序列化、反序列化:
为什么要序列化?
内存中的字典、链表如何保存到一个文件中?
如果是自己定义的类的实例,如何保存到一个文件中?
如何从文件中读取数据,并让它们在内存中再次变成自己对应的类的实例?
要设计一套协议(协议有版本,不同版本有不同的实现,规则不一样),按照某种规则,把内存中数据保存到文件中,文件是一个字节序列,所以必须把数据转换成字节序列,输出到文件,这就是序列化;反之,从文件的字节序列恢复到内存,就是反序列化;
数据转换成二进制的有序序列的过程,称为序列化;
从文件(有序的二进制序列)转换成某种对象(list、dict等)的过程,称为反序列化;
serialization序列化,将内存中对象存储下来,把它变成一个个字节(二进制);
deserialization反序列化,将文件的一个个字节(二进制)恢复成内存中的对象;
注:
持久化,存在磁盘中,掉电不丢失;
序列化保存到文件,就是持久化;
可以将数据序列化后持久化(持久化前一定要序列化),或者网络传输(通常big-edian模式),也可以从文件中或网络接收到的字节序列反序列化;
每一种高级语言都有自己的序列化;
异构平台,两端,如c/c++<-->python,要约定协议规定等;
python提供了pickle库:
pickle仅限网络两端都是python程序;
import pickle
pickle.dumps(obj,protocol,fix_imports),对象序列化,不落地,在内存中操作;
pickle.dump(obj,protocol,fix_imports),对象序列化到文件对象,存入文件;
pickle.loads(data,fix_imports,encoding,errors),对象反序列化,从内存加载;
pickle.load(file,fix_imports,encoding,errors),对象反序列化,从文件读取数据;
内建类型list、dict等,两边定义一致;
类、类属性、类方法,仅序列化类名,两端若类定义不一致,在调用后会有问题
对象属性相关的,会序列化;而类方法、类属性不会序列化(仅序列化类名)
总结:
反序列化时,类是棋子,二进制序列就是铁水;
类似,中央发往各州县的钱模;适合分布式;
rpc,远程过程调用原型;在网络编程中极为重要,底层要实现的就是序列化、反序列化;
dict、list为内建的类;
通常需要自定义类,两边的自定义要一致;
自定义的序列化要作校验;
应用:
本地序列化的情况,应用较少;
一般来说,大多数场景都应用在网络中,将数据序列化后通过网络传输到远程节点,远程服务器上的服务接收到数据将其反序列化,就可使用了;
但,要注意,远程接收端,反序列化时,必须有对应的数据类型,否则会报错,尤其是自定义类等,远程必须要有;
两端python环境要一致;是推到远端,不是远端来拉;
现在,大多数项目,都不是单机的,也不是单服务的,需要通过网络将数据传送到其节点上,这就需要大量的序列化和反序列化;
python程序间可用pickle解决序列化、反序列化;
如果是跨平台,跨语言、跨协议,pickle就不太适合了,就需要公共的协议,如xml、json、protocol buffer(glogle)等;
不同的协议,效率不同,学习曲线不同,适用不同场景,要根据不同的情况分析选型;
例(内建类型list、dict等,两边定义一致):
import pickle
lst = 'a b c'.split()
d = dict(zip('abc',range(3)))
with open('/home/python/magedu/projects/cmdb/bin','wb') as f:
pickle.dump(lst,f)
pickle.dump(d,f)
with open('/home/python/magedu/projects/cmdb/bin','rb') as f:
tmp = pickle.load(f)
print(type(tmp))
print(tmp)
tmp = pickle.load(f)
print(tmp)
注:
运行结果:
<class 'list'>
['a', 'b', 'c']
{'a': 0, 'b': 1, 'c': 2}
将bin文件放至win上;
例(类、类属性、类方法,仅序列化类名,两端若类定义不一致,在调用后会有问题):
import pickle
class AA:
def show(self):
print('abc')
aa = AA()
with open('/home/python/magedu/projects/cmdb/bin2','wb') as f:
pickle.dump(aa,f)
with open('/home/python/magedu/projects/cmdb/bin2','rb') as f:
tmp = pickle.load(f) #重新实例化后,赋给tmp,和aa是不同的对象
tmp.show()
注:
运行结果:
abc
将bin2传至win主机:
linux和win下,两端若定义的AA不一样,则有问题;
例(类、类属性、类方法,仅序列化类名,两端若类定义不一致,在调用后会有问题):
import pickle
class AA:
cccc = 'abc' #类属性
def show(self):
print('abcd')
with open('bin3','wb') as f:
pickle.dump(AA(),f)
with open('bin3','rb') as f:
t = pickle.load(f)
t.show()
print(t.cccc)
注:
运行结果:
abcd
abc
将bin3传至win主机:
例(对象属性相关的,会序列化;而类方法、类属性不会序列化(仅序列化类名)):
import pickle
class AA:
def __init__(self):
self.aa = 'cc' #对象属性,每个对象是独立的,每个对象可改变此处定义
with open('bin4','wb') as f:
pickle.dump(AA(),f)
with open('bin4','rb') as f:
t = pickle.load(f)
print(t.aa)
注:
运行结果:
cc
将bin4传至win主机:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。