设为首页 收藏本站
查看: 1694|回复: 0

[经验分享] Python HOWTOs - Argparse Tutorial

[复制链接]

尚未签到

发表于 2018-8-13 06:46:09 | 显示全部楼层 |阅读模式
  此教程倾向于大略的介绍下argparse模块,此模块被python标准库推荐用于解析命令行参数。此次编写针对于python3的版本。和python2.x稍微有所区别,尤其在异常消息这块,python3.x有了很大的改进。
  注意:还有另外两个模块也起到同样的作用,getopt和optparse。argparse是基于optparse的,故应用方法很相近。
  
  概念
  在此教程里我们会模拟ls命令开发一系列的功能:
$ 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目录的内容。那么我们需要将此信息作为位置参数进行输入指定。之所以被叫做位置参数,是因为程序依赖于它出现在命令行的位置来确认它是用来做什么的。与此概念更相关的命令诸如cp,它大多数的用法是cp SRC DEST。第一个位置表示你想拷贝的东西,第二个位置表示你想往哪里进行拷贝。
  •   现在,我们先改变一下程序的行为,在我们的例子中,我们为每个文件显示更多的信息而不仅仅只显示出各文件的名字。这这种情况下,我们使用-l可选参数
  •   这是一段帮助信息,对于你从来没有用过的程序来说这是很有帮助的,通过此信息的阅读,可以知道它是怎样工作的。
  
  
  基础知识
  让我们从一个什么都不做的最简单的例子开始:
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表现得非常方便(例如,无需指定此变量存放什么样的值)。你将注意到,此变量的名称与在add_argument()方法中给定的字符串参数echo是一致的。
  注意,尽量帮助信息显示及友好又全面,但还不是非常的有用。例如,我们可以看到我们获得了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
  现在,再做些更有用处的事情:
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将我们输入的各选项作为字符串来进行处理,除非我们告诉它是其他的类型。所以让我们告诉argparse将输入作为整数进行处理:
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
  这发生如下内容:

  •   此选项更像是一个标识而不是接收一个值。我们甚至修改了选项的名字来更加贴切的表达我们的意图。注意,我们这里指定了一个新的关键字参数,action,并且把它赋值为store_true。它的意思是,当此选项被指定,就将args.verbose设置为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

  •   我们制作了一个位置参数,故程序产生了错误。
  •   注意,位置顺序是没有关系的。
  我们将以上的功能增加多种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
  其他看起来都很好,但最后一行产生了一个bug。让我们通过限制--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执行程序处理自身verbosity参数的方法(参见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
  我们介绍另一个action,"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"。
  •   这里给出了count的用法。
  •   如果不指定-v标志,那么此标志为None。
  •   就跟我们期望的一样,指定长格式标志产生的效果是一样的。
  •   比较郁闷的是,我们的帮助信息没有很好的放映出此功能,但我们可以通过改进程序的文档来进行补充(例如通过help参数)。
  •   最后一个输出展示了一个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",
  
                    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。
  •   第三个输出不好。
  让我们来修复一下:
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,这是无法与整数进行比较的(产生了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的等级来修改输出信息的变化。下面的例子更换了使用verbosity的方法来输出更多的信息:
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()。它允许我们指定互相冲突的选项。让我们修改一下程序,使我们添加的新功能更加的合理:我们增加一个--quite选项用来于--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模块还提供了很多其他的功能。它对应的文档包含了所有的细节描述和例子。通过本教程的引导,你可以更加好的对此进行消化,而不会感觉非常的吃力。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-550842-1-1.html 上篇帖子: python中re模块的用法 下篇帖子: python:__cmp__用法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表