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) 

 其他的完善

  

做一枚奔跑的老少年!
原文地址:https://www.cnblogs.com/xiaoshayu520ly/p/10686199.html