argparse
为Python的标准库,可以用于轻松编写用户友好的命令行界面。该程序定义它需要的参数,而argparse
将找出如何从sys.argv
中解析这些参数。argparse
还将自动生成帮助和使用消息,并在用户给程序无效参数时发出错误
下面我们来使用argparse
模块来定义一些命令的使用,创建一个名为exp.py
文件,代码如下:
import json
import argparse
def lists():
"""
获取列表信息
"""
d = [i for i in range(10)]
return json.dumps(d)
def info(name):
"""
获取指定名称的信息
:param name: 名称
"""
d = {"name": name, "ip": "192.168.0.88"}
return json.dumps(d)
if __name__ == "__main__":
parse = argparse.ArgumentParser()
parse.add_argument("-l", "--list", help="获取列表信息", action="store_true")
parse.add_argument("-i", "--info", help="获取指定名称的信息")
data = vars(parse.parse_args())
if data["list"]:
print(lists())
elif data["info"]:
print(info(data["info"]))
else:
parse.print_help()
我们来使用一下该模块有哪些命令可以使用:
root@ubuntu:~# python3 exp.py -h
usage: exp.py [-h] [-l] [-i INFO]
optional arguments:
-h, --help show this help message and exit
-l, --list 获取列表信息
-i INFO, --info INFO 获取指定名称的信息
观察返回信息可以知道,我们可以使用-l
与-i
,以及默认的-h
命令。结合代码可以知道,-i
与-l
命令是通过代码add_argument()
方法进行添加的。下面,我们来使用一下它们:
root@ubuntu:~# python3 exp.py -l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
root@ubuntu:~# python3 exp.py -i linux
{"name": "linux", "ip": "192.168.0.88"}
argparse
模块中最核心的部分就是ArgumentParser
,下面来介绍一下ArgumentParser
类中所有参数的使用:
prog
程序名称。将上面exp.py
模块中对ArgumentParser
类中创建对象的代码修改如下:
parse = argparse.ArgumentParser(prog="测试prog")
下面我们再来看一下exp.py
中帮助信息的变化:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-l] [-i INFO]
optional arguments:
...
此prog
参数还有一个作用,可以使用%(prog)s
格式符来定义帮助信息,如下:
parse.add_argument("-i", "--info", help="%(prog)s程序获取指定名称的信息")
...
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-l] [-i INFO]
optional arguments:
-h, --help show this help message and exit
-l, --list 获取列表信息
-i INFO, --info INFO 测试prog程序获取指定名称的信息
usage
说明中的usage
说明。将上面exp.py
模块中对ArgumentParser
类中创建对象的代码修改如下:
parse = argparse.ArgumentParser(prog="测试prog", usage="use说明")
下面我们再来看一下帮助信息的变化,如下:
root@ubuntu:~# python3 exp.py -h
usage: use说明
optional arguments:
...
description
参数help之前显示的文本。将上面exp.py
模块中对ArgumentParser
类中创建对象的代码修改如下:
parse = argparse.ArgumentParser(prog="测试prog", description="description说明")
下面我们再来看一下帮助信息的变化,如下:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-l] [-i INFO]
description说明
optional arguments:
...
epilog
参数help之后显示的文本。将上面exp.py
模块中对ArgumentParser
类中创建对象的代码修改如下:
parse = argparse.ArgumentParser(prog="测试prog", epilog="epilog说明")
下面我们再来看一下帮助信息的变化,如下:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-l] [-i INFO]
optional arguments:
...
epilog说明
parents
添加父ArgumentParser
对象。修改一下代码如下:
parent = argparse.ArgumentParser(add_help=False)
parent.add_argument("-p", "--parent", help="parent info")
parse = argparse.ArgumentParser(prog="测试prog", parents=[parent])
下面我们再来看一下帮助信息的变化,如下:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-p PARENT] [-l] [-i INFO]
optional arguments:
-h, --help show this help message and exit
-p PARENT, --parent PARENT
parent info
-l, --list 获取列表信息
-i INFO, --info INFO 测试prog程序获取指定名称的信息
值得注意的是,添加父ArgumentParser
对象时,父对象必须带上add_help
参数,并且将其设置为False,否则ArgumentParser
将看到两个-h/--help
选项,将会引发错误
formatter_class
ArgumentParser
对象允许通过指定备用格式化类来自定义帮助格式。目前,有4个这样的类:
argparse.RawDescriptionHelpFormatter
argparse.RawTextHelpFormatter
argparse.ArgumentDefaultHelpFormatter
argparse.MetavarTypeHelpFormatter
下面对argparse.RawDescriptionHelpFormatter
使用进行举例,请看下面栗子:
parse = argparse.ArgumentParser(prog="测试prog", description="""
desc-多行文本1
desc-多行文本2
desc-多行文本3
""", epilog="""
epilog-多行文本1
epilog-多行文本2
epilog-多行文本3
""")
未设置formatter_class
参数时,帮助文档是这样显示的:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-l] [-i INFO]
desc-多行文本1 desc-多行文本2 desc-多行文本3
optional arguments:
...
epilog-多行文本1 epilog-多行文本2 epilog-多行文本3
将formatter_class
设置为argparse.RawDescriptionHelpFormatter
,帮助文档是这样显示的:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [-l] [-i INFO]
desc-多行文本1
desc-多行文本2
desc-多行文本3
optional arguments:
...
epilog-多行文本1
epilog-多行文本2
epilog-多行文本3
prefix_chars
命令行选项前缀。大多数情况下,命令行前缀都是以-
符号开头的,例如-h/--help
。如果你想使用其他的前缀作为命令行选项前缀,你可以设置此选项,如下:
parse = argparse.ArgumentParser(prog='测试prog', prefix_chars='-+')
parse.add_argument("+p", "++person", help="测试prefix_chars")
此时,我们再来看一下帮助文档是怎么显示的:
root@ubuntu:~# python3 exp.py -h
usage: 测试prog [-h] [+p PERSON]
optional arguments:
...
+p PERSON, ++person PERSON
测试prefix_chars
值得注意的是,prefix_chars
你可以设置多个命令行选项前缀,如-+&
,此时你可以使用-
、+
和&
前缀了。prefix_chars
字符串中必须包含-
字符,因为argparse
有一些默认的命令,仍是以默认的-
符号作为前缀的!!!
fromfile_prefix_chars
有时,在处理特别长的参数列表时,将参数保存在文件中而不是在命令行输入,这样是有意义的。有如下文件:
root@ubuntu:~# cat arg_strings.txt
-f
arg_strings.txt
-n
arg_strings
我们在将代码进行修改一下,如下:
parse = argparse.ArgumentParser(prog='测试prog', fromfile_prefix_chars='@')
parse.add_argument("-f", "--file", help='测试fromfile_prefix_chars')
parse.add_argument("-n", "--name", help="测试fromfile_prefix_chars")
data = vars(parse.parse_args(['@arg_strings.txt']))
print(data)
打印结果如下:
{'file': 'arg_strings.txt', 'name': 'arg_strings'}
argument_default
为参数设置全局默认值
parse = argparse.ArgumentParser(prog='测试prog', argument_default=argparse.SUPPRESS)
parse.add_argument("-f")
parse.add_argument("m")
parse.add_argument("n")
data = vars(parse.parse_args(["-f", "123", "hh", "eee"]))
print(data)
打印结果如下:
{'f': '123', 'm': 'hh', 'n': 'eee'}
conflict_handler
ArgumentParser
对象不允许两个具有相同选项字符串的操作。默认情况下,ArgumentParser
如果尝试使用已在使用的选项字符串创建参数,则对象会引发异常:
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', '--file', help='file info')
>>> parse.add_argument('--file', help='new file info')
>>> parse.print_help()
Traceback (most recent call last):
...
argparse.ArgumentError: argument --file: conflicting option string: --file
如果想要不发生报错,我们可以使用conflict_handler
参数,并且传入resolve
值,使相同选项的字符串覆盖任何旧参数。使用如下:
>>> parse = argparse.ArgumentParser(prog='测试prog', conflict_handler='resolve')
>>> parse.add_argument('-f', '--file', help='file info')
>>> parse.add_argument('--file', help='new file info')
>>> parse.print_help()
usage: 测试prog [-h] [-f FILE] [--file FILE]
optional arguments:
-h, --help show this help message and exit
-f FILE file info
--file FILE new file info
当使用parents
属性时,如果父ArgumentParser与子ArgumentParser中出现相同字符串选项时,同样可以使用conflict_handler
属性
add_help
默认情况下,ArgumentParser
对象会自动添加一个-h/--help
选项,用于显示解析器的帮助信息。如果你不想使用此选项,可以传入add_help
为False即可,效果如下:
>>> parse = argparse.ArgumentParser(prog='测试prog', add_help=False)
>>> parse.add_argument('-f', '--file', help='file info')
>>> parse.add_argument('-n', '--name', help='name info')
>>> parse.print_help()
usage: 测试prog [-f FILE] [-n NAME]
optional arguments:
-f FILE, --file FILE file info
-n NAME, --name NAME name info
可以看到,将add_help
属性设置为False之后,-h/--help
选项没有了!当使用parents
属性时,如果父ArgumentParser
中的add_help
属性没有设置为False,那么将会发生报错,所以add_help
还是有意义的
allow_abbrev
通常,当你将参数列表传递给ArgumentParser的parse_args()
方法时,它会识别长选项的缩写,使用如下:
>>> parse = argparse.ArgumentParser(prog='测试prog', allow_abbrev=False)
>>> parse.add_argument('--basketball', help='basketball')
>>> parse.parse_args(['--basket', 'haha'])
usage: 测试prog [-h] [--basketball BASKETBALL]
测试prog: error: unrecognized arguments: --basket haha
>>> parse = argparse.ArgumentParser(prog='测试prog', allow_abbrev=True)
>>> parse.add_argument('--basketball', help='basketball')
>>> parse.parse_args(['--basket', 'haha'])
Namespace(basketball='haha')
add_argument()
方法是ArgumentParser
对象的核心方法,用于定义如何解析单个命令行参数,每个参数下面都有自己更详细的描述,参数如下:
name_or_flags
为add_argument()
方法的第一个参数,必须是一系列标志或简单的参数名称。这又分为可选参数
和位置参数
,创建一个可选参数
,如下:
parse.add_argument("-f", "--file")
而位置参数可以创建如下:
parse.add_argument("bar")
举个栗子:
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument("-f", "--file", help='file info')
>>> parse.add_argument('bar')
>>> parse.parse_args(["data"])
Namespace(bar='data', file=None)
当parse_args()
被调用时,可选的参数将识别以-
符号的前缀,而其余的参数则被认为是位置参数!所以,上面栗子中,bar有值,file为空
action
ArgumentParser
对象将命令行参数与操作相关联,这些操作可以使用与它们相关联的命令行参数执行任何操作,尽管大多数操作只是向parse_args()
返回的对象添加一个属性。action关键字参数指定应该如何处理命令行参数。操作包括:
store
: 这是存储参数的值,这是默认的操作。例如:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument("-f")
>>> parse.parse_args("-f file".split())
Namespace(f='file')
store_const
: 它存储const
关键字参数指定的值,该store_const
操作最常用于指定某种标志的可选参数。例如:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', action='store_const', const='file')
>>> parse.parse_args(['-f'])
Namespace(f='file')
store_true或store_false
: 与store_const
类似,不过store_true
与store_false
只能指定True
或者False
。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-t', action='store_true')
>>> parse.add_argument('-f', action='store_false')
>>> parse.parse_args("-f -t".split())
Namespace(f=False, t=True)
append
: 它存储一个列表,并将每个参数值附加到列表中,这对于允许多次指定选项很有用。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', action='append')
>>> parse.parse_args("-f file -f info".split())
Namespace(f=['file', 'info'])
>>> parse.parse_args([])
Namespace(f=None)
append_const
: 它存储一个列表,并将const
关键字参数指定的值附加到列表中。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', action='append_const', const='file')
>>> parse.parse_args(["-f"])
Namespace(f=['file'])
count
: 计算关键字出现的次数。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', action='count')
>>> parse.parse_args(['-ffff'])
Namespace(f=4)
help
: 这将打印当前解析器中所有选项的完整帮助信息,然后退出,默认情况下,帮助操作会自动添加到解析器中。version
: 这需要调用version
关键字。使用如下:>>> import argparse
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument("--version", action='version', version='%(prog)s 1.0')
>>> parse.parse_args(["--version"])
测试prog 1.0
nargs
ArgumentParser
对象通常将单个命令行参数与要采取的单个操作关联起来。nargs
关键字参数将不同数量的命令行参数与一个操作关联起来。
N
: 一个数值,命令行中的N
个参数将被收集到一个列表当中,并且N
必须大于0,并且必须传递N
个参数,否则将报错。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', nargs=2)
>>> parse.parse_args(["-f", "1", "2"])
Namespace(f=['1', '2'])
?
: 如果可能,将从命令行使用一个参数,并将其作为单个项生成。如果不存在命令行参数,将使用default
值。值得注意的是,对于可选参数,还有一种情况,default
存在但是后面没有命令行参数,那么将使用const
值。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', nargs='?', const=2, default=1)
>>> parse.add_argument('test', nargs='?', default=3)
>>> parse.parse_args("haha -f hehe".split())
Namespace(f='hehe', test='haha')
>>> parse.parse_args('haha -f'.split())
Namespace(f=2, test='haha')
>>> parse.parse_args([])
Namespace(f=1, test=3)
args=?
还有个用途就是可选的输入与输出文件,使用如下:
>>> import sys
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('file', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
>>> parse.parse_args(["b.py"])
Namespace(file=)
*
: 所有的命令行参数都收集到一个列表当中。与action='append'
作用差不多,使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', nargs='*')
>>> parse.add_argument('bar', nargs='*')
>>> parse.parse_args('a b c -f 1 2 3'.split())
Namespace(bar=['a', 'b', 'c'], f=['1', '2', '3'])
>>> parse.parse_args([])
Namespace(bar=[], f=None)
+
: 与*
号作用相似,只不过如果没有命令行参数时,将会发生报错,使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', nargs='+')
>>> parse.add_argument('bar', nargs='+')
>>> parse.parse_args('a b -f 1 2 3'.split())
Namespace(bar=['a', 'b'], f=['1', '2', '3'])
>>> parse.parse_args([])
usage: 测试prog [-h] [-f F [F ...]] bar [bar ...]
测试prog: error: too few arguments
argparse.REMAINDER
: 把剩余的命令行参数都收集到一个列表中。使用如下:>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f')
>>> parse.add_argument('bar')
>>> parse.add_argument('info', nargs=argparse.REMAINDER)
>>> parse.parse_args('-f 1 2 3 4 5'.split())
Namespace(bar='2', f='1', info=['3', '4', '5'])
const
常量值。它的用途在上面几个参数的使用中已经涉及到,不在阐述
default
default
参数的左右也在上面有提到。对于位置参数,如果命令行中不存在命令行参数值,那么将使用default
对应的值。对于可选参数,如果命令行中不存在命令行参数值,那么僵使用const
对应的值,如果可选参数都未在命令行中出现,那么将使用default
对应的值。使用如下:
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('-f', default=2)
>>> parse.parse_args([])
Namespace(f=2)
default
参数还有一个特殊的值,default=argparse.SUPPRESS
,如果命令行参数不存在,则不会添加任何属性:
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('--foo', default=argparse.SUPPRESS)
>>> parse.parse_args([])
Namespace()
值得注意的是,这种情况只针对可选参数
有效,对于位置参数
而言,如果default
参数传值为argparse.SUPPRESS
,那么将会发生错误!!!
type
在默认情况下,ArgumentParser
对象以简单的字符串形式读取命令行参数。但是,通常命令行字符串应该被解释成另外一种类型,如float
或int
。type
参数允许add_argument()
方法允许执行任何必要的参数类型检查和转换:
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('--foo', type=int)
>>> parse.add_argument('bar', type=float)
>>> parse.parse_args(['--foo', '1', '2'])
Namespace(bar=2.0, foo=1)
对比之前的一些栗子,你会发现,如果没有使用type
参数,那么命令行中传递的参数,将全部为字符串格式!!!
为了方便使用多种类型的文件时,argparse
模块提供了FileType
类,它具有mode
、bufsize
、encoding
、errors
参数,对应着open()
函数的功能,在上面已经介绍了它的使用,不再详述。另外,type
参数还可以传入open
来打开一个文件,如下:
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('--foo', type=open)
>>> parse.parse_args(['--foo', 'b.py'])
Namespace(foo=)
type
还可以传入一个可执行的函数,如下:
>>> import argparse
>>> import math
>>> def is_even_number(s):
>>> value = int(s)
>>> if value % 2 == 1:
>>> msg = '{}不是偶数'.format(value)
>>> raise argparse.ArgumentTypeError(msg)
>>> return value
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('--foo', type=is_even_number)
>>> parse.parse_args(["--foo", "2"])
Namespace(foo=2)
>>> parse.parse_args(["--foo", "1"])
usage: 测试prog [-h] [--foo FOO]
测试prog: error: argument --foo: 1不是偶数
choice
从一组受限制的值中选择一些命令行参数,可以通过容器对象作为choice
关键字参数传递给add_argument()
方法来处理这些问题。在解析命令之前,将检查参数值,如果参数不是可接受值之一,将显示一条错误消息:
>>> import argparse
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('bar', choices=["1", "2", "3"])
>>> parse.parse_args(["1"])
Namespace(bar='1')
>>> parse.parse_args(["4"])
usage: 测试prog [-h] {1,2,3}
测试prog: error: argument bar: invalid choice: '4' (choose from '1', '2', '3')
required
通常,argparse
模块假定标识-f/--foo
为可选参数,这些参数总是可以在命令行中省略。要使选项成为必须,我们可以使用required
参数,并传值为True
到方法add_argument()
里面:
>>> import argparse
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('--foo', required=True)
>>> parse.parse_args(["--foo", "1"])
Namespace(foo='1')
>>> parse.parse_args([])
usage: 测试prog [-h] --foo FOO
测试prog: error: argument --foo is required
help
help
值是一个字符串,其中包含参数的简要描述。当用户请求帮助时,这些帮助描述将与每个参数一起显示
metavar、dest
修改可选参数的名称,使用如下:
>>> import argparse
>>> parse = argparse.ArgumentParser(prog='测试prog')
>>> parse.add_argument('--foo')
>>> parse.add_argument('--bar', metavar='BBB')
>>> parse.add_argument('--test', dest='TTT')
>>> parse.add_argument('--desc', metavar='MMM', dest='DDD')
>>> parse.parse_args(["--bar", "1", "--test", "2", "--desc", "3"])
Namespace(DDD='3', TTT='2', bar='1', foo=None)
>>> parse.print_help()
usage: 测试prog [-h] [--foo FOO] [--bar BBB] [--test TTT] [--desc MMM]
optional arguments:
-h, --help show this help message and exit
--foo FOO
--bar BBB
--test TTT
--desc MMM
至此,Over~~~