zoukankan      html  css  js  c++  java
  • 第十八天python3 序列化和反序列化

     思考:

      内存中的字典、列表、集合以及各种对象,如何保存到一个文件中?
      如果是自己定义的类的实例,如何保存到一个文件中?
      如何从文件中读取数据,并让它们在内存中再次变成自己对应的类的实例?
      要设计一套协议,按照某种规则,把内存中数据保存到文件中,文件是一个字节序列,所以必须把数据转换成字节序列,输出到文件,这就是序列化;反之,从文件的字节序列恢复到内存,就是反序列化;

    定义
    serialization 序列化
    将内存中的对象存储下来,把它变成一个个字节;--->二进制
    deserialization 反序列化
    将文件中的一个个字节恢复成内存中的对象;<---二进制
    序列化保存到文件就是持久化;
    可以将数据序列化后持久化,或者网络传输;也可以将从文件中或者从网络接收到的字节序列反序列化;

    pickle库
    python中的序列化、反序列化模块;
      dumps 对象序列化为bytes对象;
      dump 对象序列化到文件对象,就是存入文件;
      loads 从bytes对象反序列化;
      load 对象反序列化,从文件读取数据

    序列化:

    import pickle
    
    filename = 'd:/Doc/test'
    i = 100
    h = '100'
    d = {'a':1,'b':'abc','c':[1,2,3]}
    l = list('123')
    
    with open(filename,'wb') as f:
        pickle.dump(i,f)
        pickle.dump(h,f)
        pickle.dump(d,f)
        pickle.dump(l,f)

      执行该脚本,将对象序列化到文件,并用notepad++打开该文件查看它的存储信息;

    #先在普通文本模式下查看
    €Kd.€?       ?100?€?       }??a擪?b攲abc攲c擼?KKKeu.€?       ]??1攲2攲3攅.

    #二进制模式下查看

     对照ascii表查看:

      结合代码中的变量值数字100在二进制中被转化成了16进制的数字64,而字符串100、a、b、abc、1、2、3,在二进制中仍然是以字符串的形式出现,其他信息都是以乱码的形式存在;

    反序列化:

    import pickle
    
    filename = 'd:/Doc/test'
    i = 100
    h = '100'
    d = {'a':1,'b':'abc','c':[1,2,3]}
    l = list('123')
    
    with open(filename,'wb') as f:
        pickle.dump(i,f)
        pickle.dump(h,f)
        pickle.dump(d,f)
        pickle.dump(l,f)
    
    with open(filename,'rb') as f:
        for _ in range(4):
            a = pickle.load(f)
            print(a,type(a))
    # 执行结果
    PS D:Doc> & D:/Python/Python38/python.exe d:/Doc/test.py
    100 <class 'int'>
    100 <class 'str'>
    {'a': 1, 'b': 'abc', 'c': [1, 2, 3]} <class 'dict'>
    ['1', '2', '3'] <class 'list'>

    不落地的序列化和反序列化

    import pickle
    
    filename = 'd:/Doc/test'
    x = ['a',100,['abc'],{'a':1,'b':2,'c':3}]
    lst = []
    with open(filename,'wb') as f:
        for i in x:
            lst.append(pickle.dumps(i))
    
    with open(filename,'rb') as f:
        for i in lst:
            a = pickle.loads(i)
            print(a,type(a))
    # 执行结果
    PS D:Doc> & D:/Python/Python38/python.exe d:/Doc/test.py
    a <class 'str'>
    100 <class 'int'>
    ['abc'] <class 'list'>
    {'a': 1, 'b': 2, 'c': 3} <class 'dict'>

    面向对象序列化

    import pickle
    
    class AA:
        tttt = 'ABC'
        def show(self):
            print('abc')
    
    a1 = AA()
    
    sr = pickle.dumps(a1)
    print('sr={}'.format(sr))
    
    a2 = pickle.loads(sr)
    print(a2.tttt)
    a2.show()
    # 执行结果
    PS D:Doc> & D:/Python/Python38/python.exe d:/Doc/test.py
    sr=b'x80x04x95x16x00x00x00x00x00x00x00x8cx08__main__x94x8cx02AAx94x93x94)x81x94.'
    ABC        
    abc

      从上面的例子可以看出,面向对象的序列化其实就是保存了一个类名,因为所有的其他东西都是类定义的东西,是不变的,所以只序列化一个“AA”类名;反序列化的时候找到类就可以恢复一个对象;

    序列化应用
      一般来说,本地序列化的情况,应用较少,大多数场景都应用在网络传输中;将数据序列化后通过网络传输到远程节点,远程服务器上的服务将接收到的数据反序列化后,就可以使用了;但是要注意一点,远程接收端,反序列化时必须有对应的数据类型,否则就会报错;尤其时自定义类,必须远程得有一致的定义;
      现在大多数项目,都不是单机的,也不是单服务的;需要通过网络将数据传送到其他节点上去,这就需要大量的序列化、反序列化的过程;但是,python程序之间还可以都是pickle解决序列化、反序列化,如果是跨平台、跨语言、跨协议pickle就不合适了,就需要公共的协议,例如XML、Json、Protocol Buffer等;

  • 相关阅读:
    Linq To Sql 练习
    伪静态在webconfig中配置
    log4net.dll配置以及在项目中应用
    C#Windows服务安装
    .net平台推送ios消息
    asp.net下js调用session
    MAC地址泛洪攻击测试
    wifipineapple使用教程
    python程序的调试方法
    python import的用法
  • 原文地址:https://www.cnblogs.com/zhangzhide/p/15124421.html
Copyright © 2011-2022 走看看