Argparse简易教程 Argparse简易教程

Argparse简易教程

原文:Argparse Tutorial

译者:likebeta

本教程是对于Python标准库中推荐使用的命令行解析模块argparse的简单介绍。

PS:还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的optparse。因为argparse是基于optparse,所以用法很类似。

概念

让我们先用ls来展示这篇教程将要介绍的相关特性:

[cpp]  view plain  copy
  1. $ ls  
  2. cpython  devguide  prog.py  pypy  rm-unused-function.patch  
  3. $ ls pypy  
  4. ctypes_configure  demo  dotviewer  include  lib_pypy  lib-python ...  
  5. $ ls -l  
  6. total 20  
  7. drwxr-xr-x 19 wena wena 4096 Feb 18 18:51 cpython  
  8. drwxr-xr-x  4 wena wena 4096 Feb  8 12:04 devguide  
  9. -rwxr-xr-x  1 wena wena  535 Feb 19 00:05 prog.py  
  10. drwxr-xr-x 14 wena wena 4096 Feb  7 00:59 pypy  
  11. -rw-r--r--  1 wena wena  741 Feb 18 01:01 rm-unused-function.patch  
  12. $ ls --help  
  13. Usage: ls [OPTION]... [FILE]...  
  14. List information about the FILEs (the current directory by default).  
  15. Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.  
  16. ...  

从上面的四个命令,我们可以了解一些概念:

  • ls命令在没有参数的情况下也是可以使用的。默认显示当前目录的内容。
  • 如果想让它展示不同,需要给它更多的参数。这个例子中,我们想让它显示目录pypy,需要指定必要的参数。因为程序需要基于这些参数确定做些什么。这个概念类似cp, 比如最常见的cp SRC DST。第一个参数表示你要复制什么,第二个参数表示复制到哪里去。
  • 现在,我想要改变程序的行为。在示例中,我们让它显示更多的信息,不仅仅是文件名,这里的-l就是一个可选参数。
  • 最后是一个帮助文档的片段。这些帮助对于没有使用过这个程序的人很有帮助,他们可以通过简单的阅读,就可以了解程序的用法。

基础

让我们从一个简单的例子开始,它(几乎)什么都不做:

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

运行:

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

结果分析:

  • 不加任何参数运行,什么也不显示,没有什么用。
  • 第二条展示了argparse模块的好处,几乎什么都不做,却得到了一个很有用的帮助信息。
  • --help参数可简写成-h,是唯一预设的(不需要指定)。

定位参数

例子:

[cpp]  view plain  copy
  1. import argparse  
  2. parser = argparse.ArgumentParser()  
  3. parser.add_argument("echo")  
  4. args = parser.parse_args()  
  5. print args.echo  

运行:

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

结果分析:

  • 我们用到了方法add_argument(),用来指定程序需要接受的命令参数,本例中的echo
  • 现在运行程序必须指定一个参数。
  • 方法parse_args()通过分析指定的参数返回一些数据,如本例中的echo
  • 像魔法一样,argparse自动生成这些变量,你可能已经注意到变量echo和我们指定的参数相同。

虽然现在帮助信息已经很美观了,但是还不够好。例如我们知道echo是个定位参数,但是却不知道该参数的意思,只能通过猜或者读源码。下面,我们可以让它更有帮助:

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

运行:

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

再修改下:

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

运行如下:

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

运行有点问题,因为如果不指定参数类型,argparse默认它是字符串。因此我们需要告诉argparse该参数是整型。

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

运行:

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

可以运行了,程序能够在执行前过滤一些错误的参数输入。

可选参数

以上,展示了定位参数的用法。下面让我们来看看如何添加可选参数:

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

输出:

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


结果分析:

  • 当指定--verbosity时程序就显示一些东西,没指定的时候就不显示。
  • 这个参数事实上是可选的,不指定它也不会出错。如果不指定可选的参数,对应的变量就被设置为None,比如本例中的args.verbosity, 这就是为什么示例中的 if 没有执行的原因。
  • 帮助信息发生了点变化
  • 当我们使用可选参数--verbosity时,也必须指定一些值。

上面的示例中可选参数--verbosity后面接受任意的整型值,但是对于简单的程序,实际上只需要两种值,True或者False。因此可以修改上面的代码:

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

运行:

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

结果分析:

  • 现在多加一个标志来替代必须给出一些值,并修改了名称来表达我们的意思。注意现在指定了一个新的关键词action,并且赋值为store_ture。如果指定了这个可选参数,args.verbose就赋值为True,否则就为False
  • 多指定了值,它就会发出错误提示。
  • 注意帮助文档有什么不同
简写

如果你很熟悉命令行,你可能已经注意到我在上面已经提到了参数的简写,非常的简单:

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

运行如下:

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

注意帮助信息也有相应的变化。

混合使用定位参数和可选参数

再复杂一点:

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

运行:

[cpp]  view plain  copy
  1. $ python prog.py  
  2. usage: prog.py [-h] [-v] square  
  3. prog.py: error: the following arguments are required: square  
  4. $ python prog.py 4  
  5. 16  
  6. $ python prog.py 4 --verbose  
  7. the square of 4 equals 16  
  8. $ python prog.py --verbose 4  
  9. the square of 4 equals 16  
  • 为了让程序复杂点,我们重新加上了定位参数。
  • 注意到参数的顺序是没有影响的。

来看看为程序加上处理重复参数的能力会怎么样:

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

运行:

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

除了最后一个暴露了一个bug,其他的看起都来运行良好。让我们通过限制--verbosity后面跟的值来修正:

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

运行:

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

注意帮助信息和错误信息都发生了变化。

现在让我们用一种更常用的方法来处理,类似CPython处理自己的参数(参考python --help):

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


我们引入了另一个关键词count来统计可选参数出现的次数:

[cpp]  view plain  copy
  1. $ python prog.py 4  
  2. 16  
  3. $ python prog.py 4 -v  
  4. 4^2 == 16  
  5. $ python prog.py 4 -vv  
  6. the square of 4 equals 16  
  7. $ python prog.py 4 --verbosity --verbosity  
  8. the square of 4 equals 16  
  9. $ python prog.py 4 -v 1  
  10. usage: prog.py [-h] [-v] square  
  11. prog.py: error: unrecognized arguments: 1  
  12. $ python prog.py 4 -h  
  13. usage: prog.py [-h] [-v] square  
  14.   
  15. positional arguments:  
  16.   square           display a square of a given number  
  17.   
  18. optional arguments:  
  19.   -h, --help       show this help message and exit  
  20.   -v, --verbosity  increase output verbosity  
  21. $ python prog.py 4 -vvv  
  22. 16  
  • 和前面的版本相比这里多了一个关键词(类似action="store_true")。
  • 行为上也类似store_true
  • count关键词的示范,大家可能在其他地方已经看过了。
  • 就像store_ture,如果不指定-v,响应变量就会被设置为None
  • 指定完整的名称和简写效果是一样的。
  • 但是不爽的是,帮助信息并没有做出有用的提示,不过可以通过修改help来改善这个问题。
  • 最后那个输出又暴露了程序的bug

修改一下:

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

运行如下:

[cpp]  view plain  copy
  1. $ python prog.py 4 -vvv  
  2. the square of 4 equals 16  
  3. $ python prog.py 4 -vvvv  
  4. the square of 4 equals 16  
  5. $ python prog.py 4  
  6. Traceback (most recent call last):  
  7.   File "prog.py", line 11, in <module>  
  8.     if args.verbosity >= 2:  
  9. TypeError: unorderable types: NoneType() >= int()  
  • 第一个输出是正确的,修正了上个版本的问题,参数出现次数>=2时都能显示详细的信息。
  • 第三个输出还是有问题

再来修改下:

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

我们又加入了一个关键词default。设置它的默认值为0,这样可以让它兼容其他整型。注意,如果一个可选参数没有指定,它就会被设置成NoneNone是不能和整型比较的(触发[TypeError][5]异常)。

运行结果:

[cpp]  view plain  copy
  1. $ python prog.py 4  
  2. 16  

你可以使用我们所学来做很多事情,但是这仅仅是皮毛而已。argparse模块非常强大,下面来看看更多的用法。

高级用法

如果我们想扩展程序的功能,而不仅仅是求平方:

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

输出:

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

截止到目前,我们都在利用详细的级别来改变输出,下面的示例演示了利用详细的级别来显示更多输出:

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

输出:

[cpp]  view plain  copy
  1. $ python prog.py 4 2  
  2. 16  
  3. $ python prog.py 4 2 -v  
  4. 4^2 == 16  
  5. $ python prog.py 4 2 -vv  
  6. Running 'prog.py'  
  7. 4^2 == 16  
参数冲突

迄今为止,我们已经使用到了[argparse.ArgumentParser][6]的两个方法,来看看他的另一个方法add_mutually_exclusive_group()。它可以让我们指定某个参数和其他参数冲突。下面来修改下程序以对这个新方法有更多的了解:我们将加入参数--quiet,它和参数--verbose冲突,不能同时指定:

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

程序很简单,为了演示冲突,去掉了其他功能特性展示,运行结果:

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

很好理解,我们添加最后那个输出是为了展示灵活性,比如,指定参数时可以同时混用参数全称和简写。

通过前面的学习,为了以防万一,你可能想通过帮助信息来告诉用户如何使用你的程序:

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

注意下面的帮助信息,[-v | -q]表明了可以使用-v或者-q,但是不能同时使用。

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

总结

argparse模块提供了比我们展示的多得多的功能。它的文档更加详尽和深入,并且配了大量的示例。自己去深入阅读下,文档很容易理解。

原文地址:Argparse Tutorial
官方文档:argparse
另外一篇:argparse - 命令行选项与参数解析(译)

PS:第一次翻译文档,感觉到英语真的太差了~~o(>_<)o ~~

原文地址:http://blog.ixxoo.me/argparse.htm

猜你喜欢

转载自blog.csdn.net/m0_37692953/article/details/80262763