文章目录
1 argparse模块
1.1 简介
argparse是标准库中用于命令行解析的模块。
在程序中定义好需要的参数后,argparse会从sys.argv
解析它们。
argparse还可以自动生成帮助和用法消息文本,发出错误提示。
getopt模块也可以完成相同的任务。
argparse基于被弃置的optparse模块(自3.2版本)实现,用法很相似。
1.2 解析器和使用方法
argparse模块对命令行的解析是围绕参数解析器argparse.ArgumentParser
的实例建立的。
argparse.ArgumentParser
的实例有两个常用的方法:add_argument()
和parse_args()
。
其中add_argument
用于将参数及其说明关联到解析器。
parse_args
运行解析器,然后把提取到的数据放入对象。
使用argparse模块的基本步骤:
import argparse
# 实例化解析器
parser = argparse.ArgumentParser(**kwargs)
# 将参数关联到解析器
parser.add_argument(*args, **kwargs)
# 从sys.argv提取参数,转换为命名空间的属性
args = parser.parse_args(args=None, namespace=None)
parse_args接收的参数args默认是从sys.argv取的,而sys.argv的值就是外部传入的字符串列表。后续的一些测试会直接将列表传给parse_args。
# test.py
import sys
import argparse
print(sys.argv)
>>> python test.py abc -host 0.0.0.0 -port 80 xyz
['test.py', 'abc', '-host', '0.0.0.0', '-port', '80', 'xyz']
2 ArgumentParser
的初始化参数
创建ArgumentParser
实例的可选参数如下:
parser = argparse.ArgumentParser(
prog=None, usage=None, description=None, epilog=None,
parents=[], formatter_class=argparse.HelpFormatter,
prefix_chars='-', fromfile_prefix_chars=None,
argument_default=None, conflict_handler='error',
add_help=True, allow_abbrev=True, exit_on_error=True
)
注意
ArgumentParser
初始化的所需参数都是关键字参数。
-
prog
表示程序的名称,用于在help信息中展示。
默认值是os.path.basename(sys.argv[0])
。prog的值可以在后续写帮助信息时通过
%(prog)s
格式引用。 -
usage
描述程序用途,会在帮助信息中显示。
帮助信息第一行默认显示格式是usage: 程序名称 [可用选项]
。
可以通过usage参数改变这里显示的内容。 -
description
在usage之后,在参数帮助信息之前显示的文本。一般简要描述这个程序会做什么、和如何做的。
description文本默认情况下会换行,可以由参数formatter_class控制不换行。 -
epilog
在参数帮助信息之后显示的额外的对程序的描述。
epilog文本默认情况下会换行,可以由参数formatter_class控制不换行。 -
parents
ArgumentParser对象列表。
有时多个解析器会使用同一系列的参数,可以把这些参数先定义给一个父解析器,然后在其它解析器使用parents指定这个父解析器。父解析器需要指定
add_help=False
,否则解析器发现两个帮助选项就会产生一个错误。所以父解析器对帮助信息做的修改不会出现在子解析器上。
子解析器创建之后再改变父解析器,改变不会在子解析器上出现。 -
formatter_class
用于自定义帮助文档输出格式的类。
目前可选的类有四种:
argparse.RawDescriptionHelpFormatter,不会将description和epilog内容自动换行;
argparse.RawTextHelpFormatter,保留编辑帮助信息时写的所有空白符。
argparse.ArgumentDefaultsHelpFormatter,自动把参数的默认值信息加到帮助信息中。
argparse.MetavarTypeHelpFormatter,在参数说明中使用参数的type
当做参数的显示名。 -
prefix_chars
可选参数的前缀字符集,默认值是"-"
。 -
fromfile_prefix_chars
参数列表很长时,可以写在一个文件中,通过命令行传给程序。
fromfile_prefix_chars表示需要从文件中读取其他参数时,用于标识文件名的前缀字符集合。
以给定字符开头的参数都会被当做文件处理,并被它们包含的参数替换。 -
argument_default
参数的全局默认值,默认是None。 -
conflict_handler
相同的选项字符串被重复定义时,解析器会产生一个异常。
如果想重写旧的参数选项,使参数conflict_handler='resolve'
即可。 -
add_help
是否为解析器添加-h/--help
帮助选项,默认True。如果“-”符号没有被参数prefix_chars指定的字符串包含,就使用prefix_chars的第一个字符当做帮助选项的前缀。
-
allow_abbrev
如果缩写是无歧义的,是否允许缩写长选项,默认True。
这种情况下,长选项使用其前缀也能够成功传参。
如果长选项和其前缀选项是不同的定义,需要把allow_abbrev定为False。 -
exit_on_error
parse_args()
接收到错误的参数时,默认情况下解析器会打印一个错误提示并退出。
如果想要手动捕获错误,可以把exit_on_error设为False。
3 add_argument()
方法
add_argument()
用于定义单个命令行参数如何解析。方法参数如下:
ArgumentParser.add_argument(
name or flags [, action][, nargs][, const]
[, default][, type][, choices][, required]
[, help][, metavar][, dest][, deprecated]
)
-
name or flags
一个名称(name)或者多个选项字符串(flags)。
名称表示位置参数,命令行运行时处于该位置的字符串会当做参数的值。
多个选项字符串表示选项参数,命令行运行时出现这个选项时,之后的一个字符串会当做参数的值。# 添加位置参数 parser.add_argument('bar') parser.add_argument('coco') # 添加选项参数foo parser.add_argument('-f','--foo') # 解析命令行并打印 args = parser.parse_args('1 -f abc xyz'.split()) print(args)
# 打印的结果, Namespace(bar='1', coco='xyz', foo='abc')
parse_args()
会先按前缀识别选项参数,然后剩下的参数被当做位置参数按顺序依次赋值。
选项参数不受传参的顺序影响。 -
action
当参数在命令行中出现时使用的动作。action='store'
,默认值,直接存储参数的值;action='store_const'
,存储由const参数指定的值;外部不传这个参数则存None。action='store_true'
,存储True值,外部不传这个参数则存False。action='store_false'
,存储False值,外部不传这个参数则存True。action='append'
,存储为列表。用于可多次指定的选项。默认值若非空,也会存到列表且在第一位。action='append_const'
,存储列表,并将由const指定的值加到列表中。action='count'
,计算选项参数出现的次数;action='help'
,打印当前解析器中的选项和参数的完整帮助信息,然后退出。action='version'
,有一个version参数在add_argument中出现,打印该信息并退出。该选项存在时程序不会继续往后运行。action='extend'
,存储一个列表,把每个参数值加到其中。
parser = argparse.ArgumentParser() parser.add_argument('-z', action='store_const', const=3) parser.add_argument('-x', action='store_true') parser.add_argument('-y', action='store_false') parser.add_argument('-f','--foo', action='append') parser.add_argument('-c', action='count') parser.add_argument('-a','--all', action='extend', nargs="+") args = parser.parse_args('-c -f abc -a a1 a2 a3 -f xyz -c -ccc -z'.split()) print(args)
Namespace(c=5, x=False, y=True, z=3, foo=['abc', 'xyz'], all=['a1', 'a2', 'a3'])
只有对命令行参数产生消耗的action才能对位置参数使用,如store、append、extend。
可以通过传递Action子类或实现类似接口的其他对象来指定任意操作。
-
nargs
将不同数量的命令行参数关联到同一个动作。可选的值有:nargs=n
:整数值,表示把命令行中的n个参数聚集到一个列表中。nargs=1时会产生单元素列表。nargs='?'
:不在命令行指定该选项时,该选项值为default给定的默认值,在命令行指定了选项但是没有给值,选项就使用const给定的值。一般用于允许可选的输入或输出文件。nargs='*'
,所有当前命令行参数聚集到一个列表中。nargs='+'
,所有当前命令行参数聚集到一个列表中,没有命令行参数时会产生错误信息。
nargs不填的时候,解析行为由action决定。
不需要在命令行传值的action,nargs=0。 -
const
不从命令行读取,但被一些action和nargs需要的常数。 -
default
参数在命令行未出现时应当使用的值。 -
type
命令行参数应当被转换成的类型。
不要使用type=bool
,非空字符串都会转为True。
在引发AgrumentTypeError、TypeError、ValueError时,type能处理错误并显示信息。 -
choices
由一组限定的值组成的序列,该命令行参数的值只能在这个范围内选择。不在范围内会显示错误。 -
required
此命令行选项是否可省略。选项参数设置require=True
时,会变为必选参数。 -
help
一段此参数作用的简单描述。add_argument接收到的大部分关键字参数,都能在help文本以格式化的形式调用,%(default)s
、%(type)s
等。设置
help=argparse.SUPPRESS
时,该选项不会在帮助信息中显示。 -
metavar
在帮助信息中代指参数的名称,默认会把dest参数的值作为这个名称。
可以用metavar自定义这个代指使用的名称。>>> # 不使用metavar >>> parser.add_argument('bar') >>> parser.add_argument('--foo') usage: test.py [-h] [--foo FOO] bar >>> # 使用metavar >>> parser.add_argument('bar', metavar="XXX") >>> parser.add_argument('--foo', metavar="YYY") usage: test.py [-h] [--foo YYY] XXX
metavar
只影响在帮助信息中的显示,解析结果的属性名称还是由dest决定。 -
dest
dest
指命令行输入的值在parse_args
解析后的属性名称,也是放到命名空间后的属性名称。
默认情况下,位置参数的dest
是add_argument
的第一个参数;选项参数的dest是第一个长选项字符串去掉前缀--
后的部分,如果不指定长选项,就用第一个短选项去掉-
做为dest。长选项字符串中带-
的话,会在属性名称中被转换为_
。parser = argparse.ArgumentParser() # 位置参数使用第一个字符串做名称 parser.add_argument('xx', 'yy') # 使用短选项做名称 parser.add_argument('-a') # 使用长选项做名称 parser.add_argument('-b', '--bar') # 使用长选项做名称,且横线转为下划线 parser.add_argument('-c', '--count-num') # 指定dest则以指定的名称为属性名 parser.add_argument('-d', '--decode', dest='code') args = parser.parse_args('a1 -a 3 -b 5 -c 6 -d 1'.split()) print(args)
Namespace(xx='a1', a='3', bar='5', count_num='6', code='1')
-
deprecated
参数的使用是否已被弃用。用于一些在开发后期移除的命令。
4 parse_args()
方法
ArgumentParser.parse_args(args=None, namespace=None)
将参数字符串转换为对象,并将其设为命名空间的属性值。
args
是要解析的字符串列表,默认从sys.argv取。
namespace
是用于获取属性的对象,默认是空的Namespace对象。
4.1 参数args
4.1.1 基本语法
parser.add_argument("-f", "--foo")
# 选项和值分为两个字符串传入
parser.parse_args("-f 5".split())
# 对于长选项可以和值在同一个字符串,用=分开
parser.parse_args("--foo=5".split())
# 短选项可以和值连在一起
parser.parse_args("-f5".split())
# 多个短选项如果只有最后一个需要输入值,就能并在一起
parser.add_argument("-x", action="store_true")
parser.add_argument("-y", action="store_true")
parser.add_argument("-z")
parser.parse_args("-xyzZ".split())
4.1.2 包含-
的参数
# 参数值带有前缀-,可以单独插入--,表示后面的内容是一个位置参数
>>> parser.add_argument('bar')
>>> parser.parse_args("-- -1".split())
Namespace(bar='-1')
4.1.3 参数缩写
默认情况下允许将长选项缩写为前缀,只要缩写不会产生歧义。
>>> parser.add_argument('-ba135')
>>> parser.add_argument('-ba246')
>>> parser.parse_args("-ba1 xxx".split())
Namespace(ba135='xxx', ba246=None)
>>> parser.parse_args("-ba yyy".split())
usage: test.py [-h] [-ba135 BA135] [-ba246 BA246]
test.py: error: ambiguous option: -ba could match -ba135, -ba246
4.2 参数namespace
Namespace的对象。Namespace实例只是简单的可以存放属性的对象。
当需要为一个已存在的对象赋值时,可以指定参数namespace=对象名称
。
5 添加子命令
5.1 添加子命令的方法
添加子命令的格式如下:
ArgumentParser.add_subparsers(
[title][, description][, prog][,parser_class][, action]
[, option_strings][, dest][, required][, help][, metavar]
)
title
:help信息中显示的子命令的名称。默认是“subcommands”。
description
:帮助中对子命令的描述,默认None。
prog
:在子命令的帮助信息的usage处展示的名称。
parser_class
:创建子解析器的类。默认是当前解析器的类ArgumentParser。
action
:当此参数在命令行中出现时要执行动作的基本类型。
dest
:将被用于保存子命令名称的属性名;默认为None。
required
:是否必选,默认为False。
help
:在帮助中输出的子命令帮助信息,默认为 None。
metavar
:帮助信息中子命令的替代名称。
5.2 使用示例
# 创建解析器并添加参数
parser = argparse.ArgumentParser()
parser.add_argument('--all', action="store_true", help='all help')
# 子解析器控制器
subparsers = parser.add_subparsers(title="子命令", help="子命令帮助", description="子命令简介")
# 子解析器a
parser_a = subparsers.add_parser("cmda", help="子命令a")
parser_a.add_argument('bar', type=int, help='bar help')
# 子解析器b
parser_b = subparsers.add_parser("cmdb", help="子命令b")
parser_b.add_argument('--baz', choices=('X', 'Y', 'Z'), help='baz help')
print("主解析器的帮助信息")
parser.print_help()
print("子解析器a的帮助信息")
parser_a.print_help()
print("子解析器b的帮助信息")
parser_b.print_help()
帮助信息打印结果
===主解析器的帮助信息===
usage: test.py [-h] [--all] {cmda,cmdb} ...
options:
-h, --help show this help message and exit
--all all help
子命令:
子命令简介
{cmda,cmdb} 子命令帮助
cmda 子命令a
cmdb 子命令b
===子解析器a的帮助信息===
usage: test.py cmda [-h] bar
positional arguments:
bar bar help
options:
-h, --help show this help message and exit
===子解析器b的帮助信息===
usage: test.py cmdb [-h] [--baz {X,Y,Z}]
options:
-h, --help show this help message and exit
--baz {X,Y,Z} baz help
子解析器的帮助信息只会包含自己的信息,没有其它子解析器和父解析器的信息。
5.3 子命令使用别名
创建子解析器时,可以用add_parser
方法可以使用alias参数把多个字符串关联到同一个子解析器上。
subparsers.add_parser("cmda", alias=['CMDA'])
5.4 子命令关联函数
子解析器的方法set_defaults(**kwargs)
,可以接收一个函数作为绑定。
def foo_and_bar(args):
return args.foo + args.bar
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser_a = subparsers.add_parser("cmda")
parser_a.add_argument('bar', type=int)
parser_a.add_argument('foo', type=int)
parser_a.set_defaults(func=foo_and_bar)
args = parser.parse_args("cmda 1 2".split())
print(args)
print(args.func(args))
Namespace(bar=1, foo=2, func=<function foo_and_bar at 0x...>)
3
6 其它
6.1 参数分组显示
ArgumentParser.add_argument_group(title=None, description=None, *[, argument_default][, conflict_handler])
默认情况下,帮助消息会分为位置参数和选项参数两组,add_argument_group
可以自定义更好的分组。
parser = argparse.ArgumentParser()
group = parser.add_argument_group('circle')
group.add_argument('--pi', help='指定圆周率的精度', type=float, default=3.14)
group.add_argument('r', help='半径')
parser.print_help()
usage: [-h] [--pi PI] r
options:
-h, --help show this help message and exit
circle:
--pi PI 指定圆周率的精度
r 半径
6.2 互斥参数
ArgumentParser.add_mutually_exclusive_group(required=False)
创建互斥组,确保其中的参数只有一个在命令行出现。require为True时,表示互斥组中必须至少有一个在命令行出现。
6.3 部分解析
ArgumentParser.parse_known_args(args=None, namespace=None)
作用和parse_args一样,但是存在额外参数的时候不会产生错误。
6.4 打印帮助
打印简短描述:ArgumentParser.print_usage(file=None)
打印帮助信息:ArgumentParser.print_help(file=None)
file表示输出的位置,默认时sys.stdout
。