• Python进阶6---序列化与反序列化


    序列化与反序列化***

    为什么要序列化 ?

     

    定义

    pickle库

    #序列化实例
    import pickle
    lst = 'a b c'.split()
    with open('test.txt','wb+')as f:
        pickle.dump(lst,f)
    
    file = 'test.txt'
    with open(file,'wb')as f:
        s1 = 99
        s2 = 'abc'
        s3 = ['a','b',['c','d']]
    
        pickle.dump(s1,f)
        pickle.dump(s2,f)
        pickle.dump(s3,f)
    
    with open(file,'rb') as f:
        s=[]
        for i in range(3):
            s.append(pickle.load(f))
        print(s)
    #对象序列化1
    import pickle
    
    class AA:
        ttt = 'ABC'
        def show(self):
            print('abc')
    
    a1 = AA()
    sr = pickle.dumps(a1)
    print('sr={}'.format(sr))#AA
    
    a2 = pickle.loads(sr)
    print(a2.ttt)
    a2.show()
    #上面的例子中,其实就保存了一个类名,因为所有的其他东西都是类定义的东西,是不变的,
    #所以序列化只序列化了一个AA类名。反序列化的时候找到类就可以恢复一个对象。
    #对象序列化2
    import pickle
    class AAA:
        def __init__(self):
            self.tttt = 'abc'
    
    b1 = AAA()
    sr = pickle.dumps(b1)
    print('sr={}'.format(sr)) #AAA
    
    b2 = pickle.loads(sr)
    print(b2.tttt)
    
    #可以看出这回保存了AAA,tttt和abc,因为这才是每一个对象每次都变化的。但是,反序列化的时候要找到AAA类的定义,才能成功。否则会就会抛出异常。
    #可以这样理解:反序列化的时候,类是模子,二进制序列就是铁水。

    应用

    本地序列化的情况,情况较少。
    一般来说,大多数情况都应用在网络中。将数据序列化后通过网络传输到远程节点,远程服务器上的服务将接收到的数据反序列化后,就可以使用了。
    但是,要注意一点,远程接收端,反序列化时必须有对应的数据类型,否则就会报错。尤其是自定义类,必须远程得有。
    #实验
    import pickle
    class AAA:
        def __init__(self):
            self.tttt = 'abc'
    
    aaa = AAA()
    sr = pickle.dumps(aaa)
    print(sr)
    print(len(sr))
    
    file = 'text.txt'
    with open(file,'wb')as f:
        pickle.dump(aaa,f)
    #将生产的序列化发送到其他节点运行
    with open('text1.txt','rb')as f:
        a = pickle.load(f)
    
    #解决办法
    '''
    现在,大多数项目,都不是单机的,也不是单服务的。需要通过网络将数据传送到其他节点上去,这就需要大量的
    序列化、反序列化。但是,问题是,Python程序之间还可以都是用pickle解决序列化、反序列化,如果是跨平台、
    跨语言、跨协议pickle就不太合适了,就需要公共的协议。例如XML、Json、Protocol Buffer等。
    不同协议,效率不同,学习曲线不同,适用不同场景,要根据不同的情况分析选型。
    '''

    Json

    Json的数据类型

     

    实例

    {
      "person": [
        {
          "name": "tom",
          "age": 18
        },
        {
          "name": "cy",
          "age": "23"
        }
      ],
      "total": 2
    }

    json模块

    Python与Json

    Python支持少量内建数据类型到Json类型的转换

    常用方法

    dumps json编码

    dump json编码并存入文件

    loads json解码

    load dump解码,从文件读取数据

    import json
    d = {'name':'chengyu','age':20,'interest':['music','movie']}
    j = json.dumps(d)#传入一个对象,return JSONEncoder
    print(j)
    
    d1 = json.loads(j)
    print(d1)

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

    MessagePack(第三方库)

    安装

    pip install msgpack-python

    常用方法

     

    #示例:
    import msgpack
    import json
    d ={'person':[{'name':'tom','age':18},{'name':'cheng','age':23}],'total':2}
    a = json.dumps(d)
    print("json格式:{},{}".format(len(a),a))
    b = msgpack.packb(d)
    print("magpack格式:{},{}".format(len(b),b))
    
    d1 = msgpack.unpackb(b)
    print(d1)
    d1 = msgpack.unpackb(b,encoding='utf-8')
    print(d1)

    注意:MessagePack简单易用,高效压缩,支持语言丰富。
    所以,用它序列化也是一个不错的选择。

    作页:

    argparse模块

    参数分类

    基本解析

    先来一段最简单的程序

    import argparse
    parser = argparse.ArgumentParser()    #获得一个参数解析器
    args = parser.parse_args()    #分析参数
    parser.print_help()    #打印帮助
    #运行结果
    #python test.py -h
    usage:test.py [-h]
    optional arguments:
      -h, --help         show this help message and exit

    argparse不仅仅做了参数的定义和解析,还自动帮助生成了帮助信息。尤其是usage,可以看到现在定义的参数是不是自己想要的

     参数解析器ArgumentParser的参数

    位置参数解析

     

    import argparse
    parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents')    #获得一个参数解析器
    parser.add_argument('path')#位置参数
    
    args = parser.parse_args()    #分析参数
    parser.print_help()    #打印帮助
    print('*'*10,args)
    #运行结果:
    '''
    usage: ls [-h] path
    ls: error: the following arguments are required: path
    '''
    ''' 程序等定义为: ls [-h] path -h为帮助,可有可无 path为位置参数,必须提供
    '''

    传参

    import argparse
    parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents')    #获得一个参数解析器
    parser.add_argument('path')#位置参数
    
    args = parser.parse_args(('/etc',))    #分析参数,同时传入可迭代的参数
    parser.print_help()    #打印帮助
    print('*'*3,args)  #打印名词空间中收集的参数
    #运行结果:
    '''
    usage: ls [-h] path
    list directory contents
    
    positional arguments:
      path
    
    optional arguments:
      -h, --help  show this help message and exit
    *** Namespace(path='/etc')
    '''
    #注意:Namespace(path='/etc')里面的path可以通过Namespace对象访问,例如args.path

    非必须位置参数

     

    #改进1
    import argparse
    
    #获取一个参数解析器
    parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents')
    parser.add_argument('path',nargs='?',default='.',help='path help')#位置参数,可有可无,缺省值,帮助
    
    args = parser.parse_args()#分析参数,同时传入可迭代的参数
    print(args) #打印名词空间中收集的参数
    parser.print_help()#打印帮助
    '''#运行结果
    Namespace(path='path')
    usage: ls [-h] [path]
    list directory contents
    
    positional arguments:
      path        path help
    
    optional arguments:
      -h, --help  show this help message and exit
    '''

    选项参数

     -l的实现

    -a的实现

    #改进2
    import argparse
    
    #获取一个参数解析器
    parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents')
    parser.add_argument('path',nargs='?',default='.',help='path help')#位置参数,可有可无,缺省值,帮助
    parser.add_argument('-l',action='store_true',help='use a long listing format')
    parser.add_argument('-a','--all',action='store_true',help='show all files,do not ignore entries starting with .')
    
    args = parser.parse_args()#分析参数,同时传入可迭代的参数
    print(args)
    parser.print_help()
    
    '''运行结果:
    Namespace(all=False, l=False, path='path')
    usage: ls [-h] [-l] [-a] [path]
    list directory contents
    
    positional arguments:
      path        path help
    
    optional arguments:
      -h, --help  show this help message and exit
      -l          use a long listing format
      -a, --all   show all files,do not ignore entries starting with .
      '''
     
    #parser.parse_args('-l -a /tmp'.split())语句的运行结果如下:
    #Namespace(all=True, l=True, path='/tmp')

    ls业务功能的实现

     1 #最终版
     2 import argparse
     3 from pathlib import Path
     4 from datetime import datetime
     5 import stat
     6 
     7 # print(args)#d打印名词空间中收集的参数
     8 # parser.print_help()#打印帮助
     9 
    10 #获取文件类型
    11 def _getfiletype(f:Path):
    12     if f.is_dir():
    13         return 'd'
    14     elif f.is_block_device():
    15         return 'b'
    16     elif f.is_char_device():
    17         return 'c'
    18     elif f.is_socket():
    19         return 's'
    20     elif f.is_symlink():
    21         return 'l'
    22     else:
    23         return '-'
    24 
    25 modelist = ['r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x']
    26 def _getmodestr(mode:int):
    27     m = int(mode) & 0o777
    28     print(mode,m,bin(m))
    29     mstr =''
    30     # for i,v in enumerate(bin(m)[-9:]):
    31     #     if v == '1':
    32     #         mstr += modelist[i]
    33     #     else:
    34     #         mstr += '-'
    35     for i in range(8,-1,-1):
    36         if m >>i & 1:
    37             mstr += modelist[8-i]
    38         else:
    39             mstr += '-'
    40     return mstr
    41 
    42 #目标:-rw-rw-r-- 1 python python      5 Oct 25 00:07 test4
    43 #return (mode,st.st_uid,st.st_gid,size,atime,file.name)
    44 def list_dir(path,all=False,detail=False,human=False):
    45 
    46 #return "{}{}".format(size, units[depth] 即换算后的文件大小
    47     units = ['', 'K', 'M', 'G', 'T', 'P']  # ' KMGTP'
    48     def _gethuman(size: int):
    49         depth = 0
    50         while size >= 1000:
    51             size = size // 1000
    52             depth += 1
    53 
    54         return "{}{}".format(size, units[depth])
    55 
    56 #yield (mode,st.st_uid,st.st_gid,size,atime,file.name)
    57     def _showdir(path='',all=False,detail=False,human=False):
    58         '''列出本文件目录'''
    59         p = Path(path)
    60         for file in p.iterdir():
    61             if not all and str(file.name).startswith('.'):#不显示隐藏文件
    62                 continue
    63             if not detail:
    64                 yield (file.name,)
    65             else:
    66                 #mode 硬链接 属主 属组 字节 时间 name
    67                 st = file.stat()
    68                 #调用内部函数stat.filemode,功能等同于自定义getfiletype函数
    69                 mode  = stat.filemode(st.st_mode)
    70                 size = str(st.st_size)
    71                 if human:
    72                     size = _gethuman(st.st_size)
    73                 atime = datetime.fromtimestamp(st.st_atime).strftime('%Y-%m-%d %H:%M:%S')
    74                 yield (mode,st.st_nlink,st.st_uid,st.st_gid,size,atime,file.name)
    75 
    76     yield from sorted(_showdir(args.path,args.all,args.l,args.s),key=lambda x:x[-1])#等同于下面语句
    77     # for x in sorted(_showdir(args.path,args.all,args.l,args.human),key=lambda x:x[-1]):
    78     #     yield x
    79 #获取一个参数解析器
    80 parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents')
    81 parser.add_argument('path',nargs='?',default='.',help='path help')#位置参数,可有可无,缺省值,帮助
    82 parser.add_argument('-l',action='store_true',help='use a long listing format')
    83 parser.add_argument('--all','-a',action='store_true',help='show all files,do not ignore entries ')
    84 parser.add_argument('-s',action='store_true')
    85 
    86 
    87 if __name__ == '__main__':
    88     args = parser.parse_args()  # 分析参数,同时传入可迭代的参数
    89     parser.print_help()
    90     print('*'*10,args)
    91     for st in list_dir(args.path,args.all,args.s,args.l):
    92         print(st) 

     其他的完善

      

    做一枚奔跑的老少年!
  • 相关阅读:
    ComboBox中Tag的使用,转换为Enum类型
    datagridview定时分页(翻页)
    DataGridView导出excel/xml
    Log4net学习笔记及部分使用方法
    C#中Abstract 与 Virtual
    The project type is not supported by this installation?
    全国哀悼日 网站变灰装(附代码)
    设计出好的对象模式
    不仅拥有XmlDocument一样简单的XML操作方法,并且实现数据文件安全存储功能——XmlEDocument
    Remoting模仿QQ实现客户端,服务器端聊天功能
  • 原文地址:https://www.cnblogs.com/xiaoshayu520ly/p/10686199.html
Copyright © 2020-2023  润新知