SOCSEC

python之argparse模块详解

最近写python程序使用了argparse模块,感觉很好用。于是翻译了下该模块的官方文档,加深下记忆。

官方文档:【https://docs.python.org/2/howto/argparse.html

基础篇

我们以一个什么都不做的程序例子开始学习:

1
2
3
import argparse
parser=argparse.ArgumentParser()
parser.parse_args()

程序运行的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ python prog.py
$ python prog.py --help
usage: prog.py [-h]
optional arguments:
-h, --help show this help message and exit
$ python prog.py --verbose
usage: prog.py [-h]
prog.py: error: unrecognized arguments: --verbose
$ python prog.py foo
usage: prog.py [-h]
prog.py: error: unrecognized arguments: foo

可以看出:

*第一次运行脚本程序不加任何选项,结果没有任何输出。

*第二次运行脚本程序开始显示argparse模块的用处了,我们神么都没有做就得到了一个很好的帮助信息。

*--help选项或者-h选项是模块自带的,不可手动设定,否则会报错。

位置参数

一个例子:

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print args.echo

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ python prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo
$ python prog.py --help
usage: prog.py [-h] echo
positional arguments:
echo
optional arguments:
-h, --help show this help message and exit
$ python prog.py foo
foo

可以看到:

*我们使用add_argmuent()方法设定程序要接受的命令行位置参数,并命名它为echo,以显示其功能。

*现在调用我们的程序需要设定一个位置参数

*parse_args()方法将返回命令行传入我们设定的位置参数的值,在这个例子里是echo的值。

*不用额外指定变量,直接使用args.echo调用传入参数。

即使--help参数显示的帮助信息已经很nice了,我们有时候需要让用户详细了解每个参数的功能,所以我们让帮助信息更加的有用:

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print args.echo

运行结果:

1
2
3
4
5
6
7
8
$ python prog.py -h
usage: prog.py [-h] echo
positional arguments:
echo echo the string you use here
optional arguments:
-h, --help show this help message and exit

那么,我们来实现一个更有用的功能:

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number")
args = parser.parse_args()
print args.square ** 2

运行结果:

1
2
3
4
5
$ python prog.py 4
Traceback (most recent call last):
File "prog.py", line 5, <module>
args.square**2
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

额!报错了,那是因为argparse模块默认传入参数为string类型,除非手动指定类型,如下,指定类型为int:

1
2
3
4
5
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number",type=int)
args = parser.parse_args()
print args.square**2

运行结果:

1
2
3
4
5
$ python prog.py 4
16
$ python prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: 'four'

这次运行的就很好了。

可选参数

到目前为止,我们已经学会了怎么使用位置参数,下面我们来学习怎么添加可选参数:

1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
print"verbosity turned on"

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ python prog.py --verbosity 1
verbosity turned on
$ python prog.py
$ python prog.py --help
usage: prog.py [-h] [--verbosity VERBOSITY]
optional arguments:
-h, --help show this help message and exit
--verbosity VERBOSITY
increase output verbosity
$ python prog.py --verbosity
usage: prog.py [-h] [--verbosity VERBOSITY]
prog.py: error: argument --verbosity: expected one argument

可以看出:

*当--verbosity参数设定时显示对应信息,不设定时,不显示任何信息。

*该选项可以传入任何值,不设定时不报错,当可选参数不设定时,在这个例子下,args.verbosity值为None.

*帮助信息略有不同

*当使用--verbosity参数时,必须传入值,可以是任何值

上例程序中--verbosity接收任意整数值,但是对于我们程序功能来说,只需接收TrueFalse值,所以我们来变通下:

1
2
3
4
5
6
7
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
action="store_true")
args = parser.parse_args()
if args.verbose:
print "verbosity turned on"

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
prog.py --verbose
verbosity turned on
$ python prog.py --verbose 1
usage: prog.py [-h] [--verbose]
prog.py: error: unrecognized arguments: 1
$ python prog.py --help
usage: prog.py [-h] [--verbose]
optional arguments:
-h, --help show this help message and exit
--verbose increase output verbosity

可以看出:

*这个选项已经是一个flag类型的了,设定了这个参数就为True否则为False

短选项参数

以一个例子开始:

1
2
3
4
5
6
7
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", help="increase output verbosity",
action="store_true")
args = parser.parse_args()
if args.verbose:
print "verbosity turned on"

运行结果:

1
2
3
4
5
6
7
8
9
prog.py -v
verbosity turned on
$ python prog.py --help
usage: prog.py [-h] [-v]
optional arguments:
-h, --help show this help message and exit
-v, --verbose increase output verbosity

可以看出,短选项参数和可选参数用法相同。

组合位置参数和可选参数

例子复杂化:

1
2
3
4
5
6
7
8
9
10
11
12
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbose", action="store_true",
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbose:
print "the square of {} equals {}".format(args.square, answer)
else:
print answer

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
prog.py
usage: prog.py [-h] [-v] square
prog.py: error: the following arguments are required: square
$ python prog.py 4
16
$ python prog.py 4 --verbose
the square of 4 equals 16
$ python prog.py --verbose 4
the square of 4 equals 16

再发杂下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int,
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
prog.py 4
16
$ python prog.py 4 -v
usage: prog.py [-h] [-v VERBOSITY] square
prog.py: error: argument -v/--verbosity: expected one argument
$ python prog.py 4 -v 1
4^2 == 16
$ python prog.py 4 -v 2
the square of 4 equals 16
$ python prog.py 4 -v 3
16

限制下--verbosity取值范围:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
prog.py 4 -v 3
usage: prog.py [-h] [-v {0,1,2}] square
prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
$ python prog.py 4 -h
usage: prog.py [-h] [-v {0,1,2}] square
positional arguments:
square display a square of a given number
optional arguments:
-h, --help show this help message and exit
-v {0,1,2}, --verbosity {0,1,2}
increase output verbosity

下面我们来使用另一种更通用的方法来限制verbosity参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display the square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
prog.py 4
16
$ python prog.py 4 -v
4^2 == 16
$ python prog.py 4 -vv
the square of 4 equals 16
$ python prog.py 4 --verbosity --verbosity
the square of 4 equals 16
$ python prog.py 4 -v 1
usage: prog.py [-h] [-v] square
prog.py: error: unrecognized arguments: 1
$ python prog.py 4 -h
usage: prog.py [-h] [-v] square
positional arguments:
square display a square of a given number
optional arguments:
-h, --help show this help message and exit
-v, --verbosity increase output verbosity
$ python prog.py 4 -vvv
16

在这里,我们使用了另一个action——>count,它是用来计数对应的可选参数的个数,可以看出:

*现在可选参数比之前("action=store_true")更像一个flag.

*count其功能和store_true很像,如果不设定则其值为None.

*最后的输出显示了一个bug

我们来修复它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
# bugfix: replace == with >=
if args.verbosity >= 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity >= 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer

运行结果:

1
2
3
4
5
6
7
8
9
10
11
prog.py 4 -vvv
the square of 4 equals 16
$ python prog.py 4 -vvvv
the square of 4 equals 16
$ python prog.py 4
Traceback (most recent call last):
File "prog.py", line 11, in <module>
if args.verbosity >= 2:
TypeError: unorderable types: NoneType() >= int()

哦! 又有bug了,我们在修:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count", default=0,
help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity >= 2:
print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity >= 1:
print "{}^2 == {}".format(args.square, answer)
else:
print answer

在这里,我们使用了一个关键字——default。并设置为0,当然如果不设置,则值为None

运行结果:

1
2
prog.py 4
16

argparse模块很强大,到目前为止,我们只学了它其中的一点点。

更进一步

扩充下我们的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x**args.y
if args.verbosity >= 2:
print "{} to the power {} equals {}".format(args.x, args.y, answer)
elif args.verbosity >= 1:
print "{}^{} == {}".format(args.x, args.y, answer)
else:
print answer

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
prog.py
usage: prog.py [-h] [-v] x y
prog.py: error: the following arguments are required: x, y
$ python prog.py -h
usage: prog.py [-h] [-v] x y
positional arguments:
x the base
y the exponent
optional arguments:
-h, --help show this help message and exit
-v, --verbosity
$ python prog.py 4 2 -v
4^2 == 16

下面我们使用另一种方法来格式化输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x**args.y
if args.verbosity >= 2:
print "Running '{}'".format(__file__)
if args.verbosity >= 1:
print "{}^{} ==".format(args.x, args.y),
print answer

输出结果:

1
2
3
4
5
6
7
prog.py 4 2
16
$ python prog.py 4 2 -v
4^2 == 16
$ python prog.py 4 2 -vv
Running <span class="hljs-string" style="color: #d88;">'prog.py'
4^2 == 16

冲突选项参数

到目前为止我们学习了`argparse.ArgumentParser()`的两种参数,下面我们学习下`add_mutually_exclusive_group()`的冲突选项参数。冲突参数允许我们设置相互冲突的选项。下面例子我们设置`--quiet`与`--verbose`两个冲突选项:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y
if args.quiet:
print answer
elif args.verbose:
print "{} to the power {} equals {}".format(args.x, args.y, answer)
else:
print "{}^{} == {}".format(args.x, args.y, answer)

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
prog.py 4 2
4^2 == 16
$ python prog.py 4 2 -q
16
$ python prog.py 4 2 -v
4 to the power 2 equals 16
$ python prog.py 4 2 -vq
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
$ python prog.py 4 2 -v --quiet
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose

更详细的帮助文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import argparse
parser = argparse.ArgumentParser(description="calculate X to the power of Y")
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y
if args.quiet:
print answer
elif args.verbose:
print "{} to the power {} equals {}".format(args.x, args.y, answer)
else:
print "{}^{} == {}".format(args.x, args.y, answer)

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
prog.py --help
usage: prog.py [-h] [-v | -q] x y
calculate X to the power of Y
positional arguments:
x the base
y the exponent
optional arguments:
-h, --help show this help message and exit
-v, --verbose
-q, --quiet

总结

这个帮助文档只是简介了下argparse,其更强大的功能请参考其官方文档。