Argparse教程
本教程简明地介绍了Python标准库推荐使用的命令行参数解析模块 —— Argparse的使用。这里Argparse的编写环境为Python 3,一些细节有别于2.x版本,特别是一些异常消息,在3.x版本中有所改进。
注意: 有其他两个模块,也完成同样的任务。即 getopt (一个等价于C语言的getopt()) 和 弃用的 optparse。另外,Argparse 是基于 optparse,因此在使用方面非常相似。
概念
在本入门教程中,让我们通过使用ls命令来展示Argparse的功能:
$ ls
cpython devguide prog.py pypy rm-unused-function.patch
$ ls pypy
ctypes_configure demo dotviewer include lib_pypy lib-python ...
$ ls -l
total 20
drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython
drwxr-xr-x 4 wena wena 4096 Feb 8 12:04 devguide
-rwxr-xr-x 1 wena wena 535 Feb 19 00:05 prog.py
drwxr-xr-x 14 wena wena 4096 Feb 7 00:59 pypy
-rw-r--r-- 1 wena wena 741 Feb 18 01:01 rm-unused-function.patch
$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
...
从以上的四个命令中,我们能够了解以下几个基本概念:
- 命令一: ls命令在没有任何参数的情况下也是可以运行的,默认显示当前目录的内容。
- 命令二: 如果我们想要让它显示更多内容,那么我们需要给它多一点参数。比如,我们想显示一个不同的目录,pypy。我们所做的就是明确指定位置参数(Positional Argument)。这样程序就会根据命令行中的参数得知它所在的位置并进行显示。这个概念更像cp这样的命令,它的基本用法是 cp SRC DEST ,SRC表示的是您想要拷贝的文件,DEST表示你想要将文件拷贝到哪里。
- 命令三: 现在,我们想要改变程序的行为。在我们的示例中,我们想为每个文件显示更多的信息,而不仅仅是文件名。在这种情况下,-l被称为可选参数(Optinal Argument)。
- 命令四: 最后是显示帮助的文档的一个片段。这是非常有用的,当你遇到你从未使用过的命令时,你可以通过它学习怎么使用。
基本认识
让我们先从一个非常简单的例子开始(它什么也不做):
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
运行结果:
$ 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参数,就能得到一不错的帮助信息。
- 命令三 & 命令四: 指定其他参数会导致错误。
位置参数
一个示例:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print args.echo
运行结果:
$ 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_argument() 方法,用来指定程序可接受的命令行参数。在这种情况下,我将命名为符合其功能的参数名称 echo 。
- 现在要运行程序,就必须指定一个参数。
- parse_args() 方法实际上从我们的命令行参数中返回一些数据,在上面的例子中是echo。
- 这个像“魔法”一样的过程,在 Argparse 中是自动完成的。
注意:尽管自动产生的帮助看起来显示不错,目前不是那么有用。例如我们看到 echo 作为一个位置参数,但是我们仍然无法知道它是做什么用的。所以,我们增加了一些东西,使得它变得更加有用:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print args.echo
运行结果:
$ 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
现在,做一些更有用的事情:(计算输入参数 square 的平方)
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
运行结果:
$ python prog.py 4
Traceback (most recent call last):
File "prog.py", line 5, in <module>
print args.square**2
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
这个程序不能正确运行,因为 Argparse 会将输入参数当作字符串处理,所以我们需要设置它的类型:(type=int)
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
运行结果:
$ python prog.py 4
16
$ python prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: 'four'
进行得很顺利。这个程序现在甚至可以在非法输入时报错退出。
可选参数
迄今为止,我们一直在玩位置参数。让我们看看如何添加可选参数:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
print "verbosity turned on"
运行结果:
$ 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 ,这时 if 语句将判断为失败。另外,帮助消息也会相应更改。
- 命令二: 需要使用 –verbosity 参数时,必须指定值,值是什么无所谓。
上述示例接受 –verbosity 参数的任意值,但对于当前程序,实际上只需要两个值: True 或 False 。 我们相应地修改代码:
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"
运行结果:
$ python 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
结果分析:
- 命令一: args.verbose 参数现在是一个标记,而不需要一个具体的值。我们甚至更改了该参数的名称以匹配该想法。请注意,我们现在指定一个新的关键字 action ,并赋值“store_true”。 这意味着,如果指定了该参数,则将赋值 True ,不指定意味着为 False 。
- 命令二: 当你为此参数指定值时,它会报错。
- 其他: 请注意不同的帮助文本。
短参数
如果您熟悉命令行的使用,您会注意到我尚未提及到参数的简短版本的话题。
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"
运行结果:
$ python 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
注意:新功能也反映在帮助文本中。
位置参数和可选参数相结合
我们不断增加程序的复杂度:
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
运行结果:
$ python 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
- 命令一: 我们绑定了一个位置参数,因此无参数传入报错。
- 命令二 & 命令三: 请注意,顺序并不重要。
我们如何给我们这个程序提供多种详细输出(Multiple Verbosity)的格式,请看代码:
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
运行结果:
$ python 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 参数可以接受的值来解决它:
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
运行结果:
$ python 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 ,这是很常见的。它也匹配 CPython 可执行文件处理其自己的verbose参数的方式(检查 python –help 的输出):
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
我们引入了另一个动作 “count” 来计算特定可选参数的出现次数:
$ python 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=”store_true”)。这里解释一下与“计数”的不同。“计数”,就像“store_true”操作一样,如果不指定-v标志,该标志被认为是 None 。
- 命令四: 指定参数的长形式,我们也会得到相同的输出。
- 命令六: 令人遗憾的是,我们的帮助文本对于我们的脚本获得新特性支持的并不十分丰富,但总是可以通过改进脚本的文档(例如通过help关键字)来修复。
- 命令七: 最后一个输出会在我们的程序中出现一个BUG。
让我们FIX它:
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
运行结果:
$ python 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。也就是说,我们希望任何值 >= 2 尽可能冗长。
- 命令三: 存在问题。
让我们FIX这个BUG:
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,以使其与其他int值相当。请记住,默认情况下,如果未指定可选参数,将赋值None,并且不能与int值进行比较(因此报出TypeError异常)。
再次运行:
$ python prog.py 4
16
到目前为止,我们已经学到了很多东西,但我们仍只是触及了 Argparse 的表面。模块功能非常强大,在我们结束本教程之前,我们将进一步探讨一下。
更上一层楼
如果我们想扩展我们的小程序来执行其他权力,而不仅仅是求平方:
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
运行结果:
$ python 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
注意:到目前为止,我们一直在使用详细程度级别(Verbosity Level)来更改显示的文本。以下示例代替使用详细程度级别来显示更多文本:
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
运行结果:
$ python prog.py 4 2
16
$ python prog.py 4 2 -v
4^2 == 16
$ python prog.py 4 2 -vv
Running 'prog.py'
4^2 == 16
选项冲突
到目前为止,我们已经使用了两个 argparse.ArgumentParser 实例的方法。 我们来介绍第三个, add_mutually_exclusive_group()。它允许我们指定彼此冲突的参数。我们还要改变程序的其余部分,使新功能更有意义:我们将介绍 –quiet 选项,这将与 –verbose 相反:
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)
我们的程序现在更简单,为了演示,我们已经去掉了一些功能。无论如何,程序运行输出如下:
$ python 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
这种方式应该很容易遵循。最后一个命令,你可以看到程序获得的灵活性,即混合长形式参数与短格式参数结合的情况。
在我们总结之前,您可能想要告诉用户您的程序的主要目的,以防他们不知道:
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)
注意:使用说明略有不同。 注意 [-v | -q] ,它告诉我们,我们可以使用 -v 或 -q ,但不能同时使用两者:
$ python 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 模块提供了很多比这里介绍的更多的功能。它的功能文档是非常详细和完全的,有充分的例子。通过本教程,您应该很容易地消化它们,而不会感到不知所措。
原(Ying)文地址:Argparse Tutorial
近期评论