Python-argparse模块
1、使用场景
1.1、示例:一个可执行文件或者脚本都可以接收参数。
$ ls -l /etc /etc 是位置参数 -l 是短选项
1.2、如何把这些参数传递给程序呢?
从3.2开始Python提供了功能强大的参数分析的模块argparse。
2、参数分类
2.1、位置参数
参数放在那里,就要对应一个参数位置。例如/etc就是对应一个参数位置。
2.2、选项参数
必须通过前面是 - 的短选项或者 -- 的长选项,然后后面的才算该选项的参数,当然选项后面也可以没有参数。
2.3、小结
/etc对应的是位置参数,-l是选项参数。
ls -alh src
3、基本解析
3.1、示例
import argparse parser = argparse.ArgumentParser() # 获取一个参数解析器 args = parser.parse_args() # 分析参数 parser.print_help() # 打印帮助
3.2、运行结果
$ python test.py -h usage: test1.py [-h] optional arguments: -h, --help show this help message and exit # argparse不仅仅做了参数的定义和解析,还自动帮助生成了帮助信息。尤其是usage,可以看到现在定义的参数是否是自己想要的。
4、解析器的参数
4.1、参数介绍
参数名称 说明 prog 程序的名字,缺省使用 sys.argv[0] 的 basename add_help 自动为解析器增加 -h 和 --help 选项,默认为True description 为程序功能添加描述
4.2、示例
4.2.1、代码
import argparse parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents') # 获取一个参数解析器 args = parser.parse_args() # 分析参数 parser.print_help() # 打印帮助
4.2.2、运行结果
usage: ls [-h] list directory contents optional arguments: -h, --help show this help message and exit
5、位置参数解析
5.1、需求
ls 基本功能应该解决目录内容的打印。
打印的时候应该指定目录路径,需要位置参数。
5.2、示例
5.2.1、代码
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() # 打印帮助
5.2.2、运行结果
usage: ls [-h] path
ls: error: the following arguments are required: path
5.2.3、小结
程序定义为: ls [-h] path -h为帮助选项,可有可无 path为位置参数,必须提供
6、传参
6.1、parse_args函数介绍
args 参数列表,一个可迭代对象。内部会把可迭代对象转换成list。如果为None则使用命令行传入参数,非None则使用args参数的可迭代对象。
6.2、示例
import argparse parser = argparse.ArgumentParser(prog='ls',add_help=True,description='list directory contents') # 获取一个参数解析器 parser.add_argument('path') args = parser.parse_args(('/etc',)) # 分析参数 print(args,args.path) parser.print_help() # 打印帮助
6.3、运行结果
Namespace(path='/etc') /etc usage: ls [-h] path list directory contents positional arguments: path optional arguments: -h, --help show this help message and exit Process finished with exit code 0
6.4、小结
Namespace(path='/etc')里面的path参数存储在了一个Namespace对象内的属性上,可以通过Namespace对象属性来访问,例如args.path
7、非必须位置参数
7.1、问题点
上面的代码必须输入位置参数,否则会报错。 usage: ls [-h] path ls: error: the following arguments are required: path 但有时候,ls命令不输入任何路径的话就表示列出当前目录的文件列表。
7.2、示例
7.2.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() # 打印帮助
7.2.2、运行结果
Namespace(path='.') usage: ls [-h] [path] list directory contents positional arguments: path path help optional arguments: -h, --help show this help message and exit
7.2.3、小结
可以看出path也变成可选的位置参数,没有提供就使用默认值 .点号 表示当前路径。 help 表示帮助文档中这个参数的描述 nargs 表示这个参数接收结果参数 ? 表示可有可无 + 表示至少一个 * 可以任意个 数字表示必须是指定数目个 default 表示如果不提供该参数,就使用这个值。一般和?、*配合,因为它们都可以不提供位置参数,不提供就用缺省值
8、选项参数
8.1、-l的实现
8.1.1、问题点
parser.add_argument('-l') 就增加了选项参数,参数定义为 ls [-h][-l L] [path] 和我们要的形式有一点出入,我们期望的是 [-l] ,怎么解决? nargs能够解决吗? parser.add_argument('-l', nargs='?') ls [-h][-l [L]] [path] -l还不是可选参数。 那么,直接把nargs=0,意思就是让这个选项接收0个参数,如下:parser.add_argument('-l', nargs=0)结果,抛出异常 raise ValueError('nargs for store actions must be > 0; if you ' ValueError: nargs for store actions must be > 0; if you have nothing to store, actions such as store true or store const may be more appropriate
看来nargs是控制位置参数和选项参数的,不能影响选项参数的参数。
8.1.2、action
为了这个问题,使用action参数 parser.add_argument('-l', action='store_true') 看到命令定义变成了 ls [-h] [-l] [path] 提供-l选项,例如 ls -l 得到Namespace(l=True, path='.'),提供-l值是True ls 得到Namespace(l=False, path='.'),未提供-l值是False 这样同True、False来判断用户是否提供了该选项 parser.add_argument('-l', action='store_const', const = 20) # 提供-l选项,属性值为20;否则,对应值为None
8.2、-a的实现
parser.add_argument('-a', '--all', action='store_true') # 长短选项同时给
9、属性名称
9.1、语法
参数都是Namespace对象的属性,如果想指定这些属性名,可以使用dest。 parser.add_argument('-l', action='store_true', dest='longfmt')
9.2、代码
import argparse # 获得一个参数解析器 parser = argparse.ArgumentParser(prog='ls', add_help=True, description='list directory contents') parser.add_argument('path', nargs='?', default='.', help="directory") # 位置参数,可有可无,缺省值,帮助 parser.add_argument('-l', action='store_true', dest='longfmt', 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() # 打印帮助
9.3、运行结果
Namespace(path='.', longfmt=False, all=False) usage: ls [-h] [-l] [-a] [path] list directory contents positional arguments: path directory 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 .
10、ls业务功能的实现
10.1、需求
到目前为止,已经解决了参数的定义和传参的问题,下面就要解决业务问题: 1. 列出所有指定路径的文件,默认是不递归的 2. -a 显示所有文件,包括隐藏文件 3. -l 详细列表模式显示
10.2、代码
import argparse from pathlib import Path from datetime import datetime import stat parser = argparse.ArgumentParser(prog='ls', add_help=False, description='list directory contents') parser.add_argument('path', nargs='?', default='.', help="directory") # 位置参数,可有可无,缺省值,帮助 parser.add_argument('-l', action='store_true', dest='long', help='use a long listing format') parser.add_argument('-a', '--all', action='store_true', help='show all files, do not ignore entries starting with .') parser.add_argument('-r', '--reverse', action='store_true', help="reverse order while sorting") parser.add_argument('-h', '--human-readable', action='store_true', dest='human', help='with -l, print sizes in human readable format') def _gethuman(size: int): units = " KMGTP" depth = 0 while size > 1000 and depth < len(units) - 1: # 当前size大于1000,且depth不是最后一个进入循环 depth += 1 size //= 1000 return "{}{}".format(size, units[depth] if depth else '') def _listdir(path, all, detail, reverse, human): p = Path(path) for i in p.iterdir(): if not all and i.name.startswith('.'): # 不显示隐藏文件 continue if not detail: yield (i.name,) else: # -rw-rw-r-- 1 python python 5 Oct 25 00:07 test4 # mode 硬链接 属主 属组 字节 时间 name st = i.stat() mode = stat.filemode(st.st_mode) mtime = datetime.fromtimestamp(st.st_atime).strftime('%Y/%m/%d %H:%M:%S') size = st.st_size if not human else _gethuman(st.st_size) yield (mode, st.st_nlink, st.st_uid, st.st_gid, size, mtime, i.name) def listdir(path, all=False, detail=False, reverse=False, human=False): """详细列出本目录""" return sorted(_listdir(path, all, detail, reverse, human), key=lambda x: x[len(x) - 1], reverse=reverse) if __name__ == '__main__': # args = parser.parse_args('-lrha'.split()) # 分析参数,同时传入可迭代的参数 args = parser.parse_args() print(args) # 打印名词空间中收集的参数 parser.print_help() # 打印帮助 files = listdir(args.path, args.all, args.long, args.reverse, args.human) print(*files, sep='\n')

浙公网安备 33010602011771号