为什么要序列化
内存中的字典、列表、集合以及各种对象,如何保存到一个文件中。
设计一套协议,按照某种规则,把内存中的数据保存到文件中,文件是一个个字节序列。所以必须把数据额转换为字节序列,输出到文件,这就是序列化,反之,从文件的字节 序列恢复到内存中,就是反序列化。
1、定义
Serialization系列化,将内存中对象存储下来,把他变成一个个字节。二进制。
deSerialization反序列化,将文件的一个个字节到内存中。
序列胡保存到文件就是持久化。
可将数据序列化后持久化,或者网络传输,也可以将文件中或者网络接受到的字节序列反序列化。
2、pickle库
Python中的序列化、反序列化模块
dumps对象序列化为bytes对象
dump对象序列化到文件对象,就是存入到文件。
loads从bytes对象反序列化。
load对象反序列化,从文件读取数据.
##
import pickle
filename = 'ser'
x= 'a'
y = '100'
z = '100'
with open(filename,'wb') as f:
    pickle.dump(x,f)
    pickle.dump(y,f)
    pickle.dump(z,f)
with open(filename,'rb')as f:
    for _ in range(3):
        a = pickle.load(f)
        print(a,type(a)) 
还原的时候不一定是完全一样的。
序列化应用:一般来说,本地序列化的情况,应用较少,大多数都是用在网络传输上面的。
将数据序列化后通过网络传输到远程节点,远程服务器上的服务将接受到的数据反序列化后,就可以使用了。
但是,要注意的是,远程接收端,反序列化时候必须有对应的数据类型,否则就会报错。尤其是自己定义的类。必须远程得有一致的定义。
3、Json
1)是一种轻量级的数据交换格式,基于ECMAScript(w3c制定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
2)数据类型
值
双引号引起来的字符串,数值,true和flase,null,对象,数组,这些都是值。
字符串
由双引号包围起来的任意字符的组合,可以有转义字符。
数值:有正负,整数,浮点数。
对象:无序的键值对的集合。
格式:{key1:value1,.....keyn:valuen}
Key必须是一个字符串,需要双引号包围这个字符。
Value可以是任意合法的值。
数组:有序的值的集合
格式:[value1,....valuen]
例子:
2) json模块
Python与json
Python支持少量内建数据类型到json类型的转换。
|   Python类型  |  
     Json类型  |  
  
|   True  |  
     True  |  
  
|   False  |  
     False  |  
  
|   None  |  
     Null  |  
  
|   Str  |  
     String  |  
  
|   Int  |  
     Integer  |  
  
|   Float  |  
     Float  |  
  
|   List  |  
     Array  |  
  
|   Dict  |  
     obiect  |  
  
3) 常用的方法
|   Python 类型  |  
     Json类型  |  
  
|   Dumps  |  
     Json编码  |  
  
|   Dump  |  
     Json编码并写入文件  |  
  
|   Loads  |  
     Json解码  |  
  
|   Load  |  
     Json解码,从文件读取数据  |  
  
import json
d = {'name':'tom','age':20,'interest':['music','movie']}
j = json.dumps(d)
print(j)
d1 = json.loads(j)
print(d1) 
{"name": "tom", "age": 20, "interest": ["music", "movie"]}
{'name': 'tom', 'age': 20, 'interest': ['music', 'movie']}
一般json编码的数据就很少落地,数据都是通过网络传输。传输的时候要考虑压缩。
本质上来说就是一个文本,就是个字符串。
Json很简单,几乎语言编程都支持json,所以应用范围十分广泛。
4、MessagePack
是一个基于二进制高效的对象化序列类库,可用于跨语言通信。
可以像json那样,在许多种需要之间交换结构对象。
比json更快速也更轻巧。
支持python,ruby,java,C/C++等众多语言。
安装:
Pip install msgpack-python
常用方法
Packb序列化对象,提供了dumps兼容pickle和json
Unpackb反序列化对象,提供了loads来兼容
Pack序列化对象保存到文件对象,提供了dump来兼容
Unpack反序列化对象保存到文件对象,提供了load来兼容。
##
import json
import msgpack
d = {'person':[{'name':'tom','age':18},{'name':'jerry','age':16}],'total':2}
j = json.dumps(d)
m =msgpack.dumps(d)
print('json={},msgpack={}'.format(len(j),len(m)))
print(j.encode(),len(j.encode()))
print(m)
u = msgpack.unpackb(m)
print(type(u),u)
u = msgpack.unpackb(m,encoding='utf-8')
print(type(u),u) 
MessagePack简单易用,高效压缩,支持的语言丰富
序列化也是一种很好的选择。
简单易用,高效压缩,支持语言丰富,所以,用它序列化是一种很好的选择。
6、argparse模块
1)一个可执行文件或者脚本都可以接收参数。
ls -l/etc /etc是位置参数 -l 是短选项
如何将参数传递到程序,就使用参数分析模块argparse
1) 参数分类。
参数分为:位置参数,参数放在哪里,就要对应一个参数位置,例如/etc 就是对应的一个参数位置。
选项参数,必须通过前面 - 的短选项或者 --的长选项,然后后面的才算是参数,短选项后面也可以没有参数。
/etc 对应的就是位置参数, -l是选项参数。
3)基本解析
import argparse
parser = argparse.ArgumentParser()
args = parser.parse_args()
parser.print_help() 
usage: argparse模块使用.py [-h]
optional arguments:
-h, --help show this help message and exit
Argparse不仅仅做了参数的定义和解析,还自动生成了帮助信息。Usage,可以看到现在定义的参数是否是自己想要的。
4)解析器的参数
|   参数名称  |  
     说明  |  
  
|   Prog  |  
     程序的名字,缺省使用,sys.argv[0]  |  
  
|   add_help  |  
     自动生成解析器增加 - h和--help选项,默认为True  |  
  
|   description  |  
     为程序添加功能描述  |  
  
import argparse
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
args = parser.parse_args()
parser.print_help() 
usage: ls [-h]
list directorycontents
optional arguments:
-h, --help show this help message and exit
2) 位置参数解析器
ls 基本功能解决目录内容的打印。
打印的时候应该制定目录路径,需要的位置参数。
import argparse
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
parser.add_argument('path')
args = parser.parse_args()  #分析参数
parser.print_help()      #打印帮助 
usage: ls [-h] path
ls: error: the following arguments are required: path
程序等定义为
ls [-h] path
-h为帮助,可有可无
path 为位置参数,必须提供。
6)传参
Parse_args(args=None,namespace=None)
args参数列表,一个可迭代对象,内部会把可迭代对象转换成list,如果为None则使用命令行传入参数,非None则使用args参数的可迭代对象。
import argparse
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
parser.add_argument('path')   #位置参数
args = parser.parse_args(('/etc',))  #分析参数
print(args)      #打印名词空间中收集的参数
parser.print_help()      #打印帮助 
Namespace(path='/etc')
usage: ls [-h] path
list directorycontents
positional arguments:
path
optional arguments:
-h, --help show this help message and exit
Namespace(path='/etc')里面的path参数存储在一个Namespace对象内的属性上,,可以通过Namespace对象属相来访问。args.path
7)非必须位置参数。
必须输入位置参数,否则会报错。
有些时候ls命令不需要输入任何路径就表示列出当前目录的文件列表。
import argparse
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
parser.add_argument('path',nargs='?',default='.',help='path help')   #位置参数,可有,可无,缺省值,帮助
args = parser.parse_args()  #分析参数
print(args)      #打印名词空间中收集的参数
parser.print_help()      #打印帮助 
Namespace(path='.')
usage: ls [-h] [path]
list directorycontents
positional arguments:
path path help
optional arguments:
-h, --help show this help message and exit
看到path也变成了可选位置参数,没有提供默认值.表示当前的路径。
.help表示帮助文档中这个参数的描述。
.nargs表示这个参数接受结果参数,?表示可有可无,+表示至少一个,*表示任意个,数字表示必须是制定数目个。
.default表示如果不提供该参数,就一直使用这个值,一般和?、*配合,因为他们都可以不提供位置参数,不提供就是使用缺省值。
8)选项参数
-l 的实现:
-a 的实现。长选项同时给出,
import argparse
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
parser.add_argument('path',nargs='?',default='.',help='path help')   #位置参数,可有,可无,缺省值,帮助
parser.add_argument('-l',action ='store_true',help = 'use a one 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='.')
usage: ls [-h] [-l] [-a] [path]
list directorycontents
positional arguments:
path path help
optional arguments:
-h, --help show this help message and exit
-l use a one listing format
-a, --all show all files,do not ignore entries starting with .
1) ls 业务功能的实现。
上面解决了参数的定义和传参的问题,下面解决业务问题:
(1) .列出所有指定路径的文件,默认是不递归的。
(2) -a显示所有文件,包括隐藏文件。
(3) -l详细列表模式显示。
代码实现:listdirdetail和listdir
import argparse
from pathlib import Path
from datetime import datetime
#获得一个参数解析器
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
parser.add_argument('path',nargs='?',default='.',help='path help')   #位置参数,可有,可无,缺省值,帮助
parser.add_argument('-l',action ='store_true',help = 'use a one 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()      #打印帮助
def listdir(path,all=False):
    p = Path(path)
    for i in p.iterdir():
        if not all and i.name.startswith('.'):  #不显示隐藏文件
            continue
        yield  i.name
print(list(listdir(args.path)))
#获取文件类型
def _getfiletype(f:path):
    # f = Path(path)
    if f.is_dir():
        return 'd'
    elif f.is_block_device():
        return 'b'
    elif f.is_char_device():
        return 'c'
    elif f.is_socket():
        return 's'
    elif f.is_symlink():
        return 'l'
    else:
        return '-'
##显示文件权限等  mode
modelist = dict(zip(range(9),['r','w','x','r','w','x','r','w','x']))
def _getmodestr(mode:int):
    m = mode &0o777
    mstr = ''
    for i in range(8,-1,-1):
        if m >>i & 1:
            mstr += modelist[8-i]
        else:
            mstr +='-'
    return mstr
def listdirdetail(path,all=False,detail=False):
    p = Path(path)
    for i in p.iterdir():
        if not all and i.name.startswith('.'):
            continue
        if not detail:
            yield (i.name,)
        else:
            stat = i.stat()
            # t  = _setfiletype(i)
            mode = _getfiletype(i)+_getmodestr(stat.st_mode)
            atime = datetime.fromtimestamp(stat.st_atime).strptime('%Y %m %d %H:%M:%S')
            yield (mode,stat.st_nlink,stat.st_uid,stat.st_gid,stat.st_size,atime,i.name)
for x in listdir(args.path):
    print(x) 
Mode是整数,八进制描述的权限,最终显示rwx的格式。
modelist = dict(zip(range(9),['r','w','x','r','w','x','r','w','x']))
 def _getmodestr(mode:int):
     m = mode &0o777
     mstr = ''
     for i in range(8,-1,-1):
         if m >>i & 1:
             mstr += modelist[8-i]
         else:
             mstr +='-'
     return mstr
2) 排序
显示的文件按照文件名的升序排序输出。
Sorted(listdir(args.path,detail=True),key=lambda x:x[len(x)-1])
3) 完整代码:
import argparse
from pathlib import Path
from datetime import datetime
#获得一个参数解析器
parser = argparse.ArgumentParser(prog= 'ls',add_help=True,description='list directorycontents')
parser.add_argument('path',nargs='?',default='.',help='path help')   #位置参数,可有,可无,缺省值,帮助
parser.add_argument('-l',action ='store_true',help = 'use a one listing format')
parser.add_argument('-a','--all',action ='store_true',help='show all files,do not ignore entries starting with .')
def listdir(path,all=False,detail=False):
    def _getfiletype(f: path):
        if f.is_dir():
            return 'd'
        elif f.is_block_device():
            return 'b'
        elif f.is_char_device():
            return 'c'
        elif f.is_socket():
            return 's'
        elif f.is_symlink():
            return 'l'
        else:
            return '-'
    modelist = dict(zip(range(9), ['r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x']))
    def _getmodestr(mode: int):
        m = mode & 0o777
        mstr = ''
        for i in range(8, -1, -1):
            if m >> i & 1:
                mstr += modelist[8 - i]
            else:
                mstr += '-'
        return mstr
    def _listdir(path, all=False, detail=False):
        p = Path(path)
        for i in p.iterdir():
            if not all and i.name.startswith('.'):
                continue
            if not detail:
                yield (i.name,)
            else:
                stat = i.stat()
                # t  = _setfiletype(i)
                mode = _getfiletype(i) + _getmodestr(stat.st_mode)
                atime = datetime.fromtimestamp(stat.st_atime).strptime('%Y %m %d %H:%M:%S')
                yield (mode, stat.st_nlink, stat.st_uid, stat.st_gid, stat.st_size, atime, i.name)
    yield from sorted(_listdir(path, all, detail), key=lambda x: x[len(x) - 1])
if __name__ == '__main__':
    args = parser.parse_args()  # 分析参数
    print(args)  # 打印名词空间中收集的参数
    parser.print_help()  # 打印帮助
    files = listdir(args.path,args.all,args.l) 
4) -h的实现
-h ,-human-readable,如果-l存在,-h有效。
import argparse
from pathlib import Path
from datetime import datetime
parser = argparse.ArgumentParser(prog='ls',description='list directory contents',add_help=False)
parser.add_argument('path',nargs='?',default='.',help='path help')
parser.add_argument('-h','--human-readable',action='store_true',help='with -l,print sizes in human readable format')
# args = parser.parse_args()  # 分析参数
# print(args)  # 打印名词空间中收集的参数
# parser.print_help()  # 打印帮助
def listdir(path,all=False,detail=False,human=False):
    def _getfiletype(f:path):
        """获取文件的类型"""
        if f.is_dir():
            return 'd'
        elif f.is_block_device():
            return 'b'
        elif f.is_char_device():
            return 'c'
        elif f.is_socket():
            return 's'
        elif f.is_symlink():
            return 'l'
        elif f.is_fifo():
            return 'p'
        else:
            return '-'
    modelist = dict(zip(range(9),['r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x']))
    def _getmodest(mode:int):
        m =mode & 0o777
        mstr = ''
        for x in range(8,-1,-1):
            if m >> i & 1:
                mstr += modelist[8-i]
            else:
                mstr += '-'
        return mstr
    def _gethuman(size: int):
        units = 'KMGTP'
        depth = 0
        while size >= 1000:
            size = size // 1000
            depth += 1
        return '{}{}'.format(size, units[depth])
    def _listdir(path,all=False,detail=False,human=False):
        p =Path(path)
        for i in p.iterdir():
            if not all and i.name.startswith('.'):
                continue
            if not detail:
                yield (i.name,)
            else:
                stat = i.stat()
                # t  = _setfiletype(i)
                mode = _getfiletype(i) + _getmodestr(stat.st_mode)
                atime = datetime.fromtimestamp(stat.st_atime).strptime('%Y %m %d %H:%M:%S')
                yield (mode, stat.st_nlink, stat.st_uid, stat.st_gid, stat.st_size, atime, i.name)
    yield from sorted(_listdir(path, all, detail), key=lambda x: x[len(x) - 1])
if __name__ == '__main__':
    args = parser.parse_args()  # 分析参数
    print(args)  # 打印名词空间中收集的参数
    parser.print_help()  # 打印帮助
    files = listdir(args.path,args.all,args.l) 
5) 改进mode的模块
使用stat模块
import stat
from pathlib import Path
stat.filemode(Path().stat().st_mode)
6) 最终代码:
import argparse
import stat
from pathlib import Path
from datetime import datetime
parser = argparse.ArgumentParser(prog='ls',description='list directory contents',add_help=False)
parser.add_argument('path',nargs='?',default='.',help='path help')
parser.add_argument('-h','--human-readable',action='store_true',help='with -l,print sizes in human readable format')
parser.add_argument('-l',action ='store_true',help = 'use a one 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()  # 打印帮助
def listdir(path,all=False,detail=False,human=False):
    def _gethuman(size: int):
        units = 'KMGTP'
        depth = 0
        while size >= 1000:
            size = size // 1000
            depth += 1
        return '{}{}'.format(size, units[depth])
    def _listdir(path, all=False, detail=False, human=False):
        p = Path(path)
        for i in p.iterdir():
            if not all and i.name.startswith('.'):
                continue
            if not detail:
                yield (i.name,)
            else:
                st = i.stat()
                # t  = _setfiletype(i)
                mode = stat.filemode(st.st_mode)
                atime = datetime.fromtimestamp(st.st_atime).strptime('%Y %m %d %H:%M:%S')
                size = str(st.st_size) if not huam else _gethuman(st.st_size)
                yield (mode, st.st_nlink, st.st_uid, st.st_gid, size, atime, i.name)
    yield from sorted(_listdir(path, all, detail), key=lambda x: x[len(x) - 1])
if __name__ == '__main__':
    args = parser.parse_args()  # 分析参数
    print(args)  # 打印名词空间中收集的参数
    parser.print_help()  # 打印帮助
    files = listdir(args.path, args.all, args.l)
                    来源:oschina
链接:https://my.oschina.net/u/4365809/blog/3755083