序列化与反序列化***
为什么要序列化 ?
定义
pickle库
#序列化实例
importpickle
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= 99s2= '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
importpickleclassAA:
ttt= 'ABC'
defshow(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
importpickleclassAAA: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类的定义,才能成功。否则会就会抛出异常。#可以这样理解:反序列化的时候,类是模子,二进制序列就是铁水。
应用
本地序列化的情况,情况较少。
一般来说,大多数情况都应用在网络中。将数据序列化后通过网络传输到远程节点,远程服务器上的服务将接收到的数据反序列化后,就可以使用了。
但是,要注意一点,远程接收端,反序列化时必须有对应的数据类型,否则就会报错。尤其是自定义类,必须远程得有。
#实验
importpickleclassAAA: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解码,从文件读取数据
importjson
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
常用方法
#示例:
importmsgpackimportjson
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模块
参数分类
基本解析
先来一段最简单的程序
importargparse
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的参数
位置参数解析
importargparse
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为位置参数,必须提供'''
传参
importargparse
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
importargparse#获取一个参数解析器
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
importargparse#获取一个参数解析器
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 importargparse3 from pathlib importPath4 from datetime importdatetime5 importstat6
7 #print(args)#d打印名词空间中收集的参数
8 #parser.print_help()#打印帮助
9
10 #获取文件类型
11 def_getfiletype(f:Path):12 iff.is_dir():13 return 'd'
14 eliff.is_block_device():15 return 'b'
16 eliff.is_char_device():17 return 'c'
18 eliff.is_socket():19 return 's'
20 eliff.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) &0o77728 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 returnmstr41
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 =050 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 inp.iterdir():61 if not all and str(file.name).startswith('.'):#不显示隐藏文件
62 continue
63 if notdetail: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 ifhuman: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 inlist_dir(args.path,args.all,args.s,args.l):92 print(st)
其他的完善