argparser模块学习

作者: Edward_f0cus | 来源:发表于2016-01-26 00:23 被阅读7664次

    经常用的模块, 也是老用老忘, 用一次学一次. 写篇blog, 加深印象. refer to: python howto

    argument和parameter的区别:

    其实跟今天的主题没多大关系, 顺便说一下, 因为看一些英文的技术文章, 会经常用这两个概念.
    parameter就相当于java里的"形参":
    方法/函数定义时在括号里的参数

    def explain_param_vs_arg(param1, param2):
            print param1, param2 
    

    argument就是所谓"实参":
    调用方法/函数时括号里的参数

    explain_param_vs_arg("arg1", "arg2")
    
    Positional arguments:

    例子:

    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
    

    上面的例子,基本没什么用. 来个有用点的:

    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
    

    加了help参数之后, -h就加了对echo这个参数的说明.
    来个更有用点的:

    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把我们给的参数认成了string. 我们得告诉TA把square当成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'
    

    这把就对了. 如果参数非法了还会报错.

    Optional arguments

    前面介绍了positional arguments. 接下来我们看看optional arguments:

    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被赋值的时候显示点什么, 没被赋值的时候什么都不显示.
    • 所谓optional arguments, 取意译就是"选择性参数". 我们可以看到当不使用--verbosity的时候是不会报错的. args.verbosity的值也是None
    • help信息也显示有点不一样. 加了[--verbosity VERSOSITY].
    • 当我们使用--verbosity的时候, 就要给TA赋个值, 否则会报错.

    上面的例子可以接受任意的整数作为--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
    

    说明:

    • 这个选项现在不止是一个需要赋值的flag. 我们甚至给TA改了个名字. 我们还新指定了一个关键字, action. 同时吧TA赋值成"store_true". 这么做的意思是, 如果使用verbose, 就把True赋值给args.verbose. 如果不使用, 就给TA赋False.
    • 注意help text也发生了变化.
    Short options

    如果你经常用terminal命令行模式, 你就会发现我还没说short options. 实现起来其实非常简单.

    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
    

    可以看到在help text里有对应的改变.

    混用positional和optional arguments

    让代码来的更复杂点吧:

    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
    
    • 我们又把那个positional argument带回来了
    • 注意, 赋值的顺序并没影响

    我们再把以前的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来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", 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
    

    可以看到在error message里也反应出我们的改变.
    接下来, 我们来看下verbosity的另一种玩法, 这种玩法其实更常见, 更符合cpython使用参数的风格(试试python --verison):

    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". 去统计一个optional argument的出现次数.

    $ 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
    
    • 跟前面的"store_true"一样, 如果不使用, 就会默认赋值为"None".
    • 这就是action"count"的效果. 你们肯定也在其他程序中见过.
    • 最后的输出还是看起来怪怪的.

    我们来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()
    
    • 从前两个输出看起来工作的不错, fix了我们的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", 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
    

    我们这里介绍了另一个keyword, default. 用了default就会把默认值设置成0. 一定要记住如果不给positional argument赋值, 默认的就会赋值为None. 是不能跟数字做比较的.

    $ python prog.py 4
    16
    

    目前介绍的功能已经能应付很多情况了. 在结束之前, 我们再来点更猛的吧.

    更高级的用法

    我们扩展一下这个例子, 来显示更多内容:

    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, answer)
    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
    $ python prog.py 4 2 -v
    4^2 == 16
    $ python prog.py 4 2 -vv
    Running 'prog.py'
    4^2 == 16
    
    处理冲突

    我们在例子中加一个argument: --quiet. quiet表示如果不想用verbose的显示方式就用quiet. 它们是互斥的关系. 我们可以这么实现:

    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)
    

    输出:

    $ 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
    

    相关文章

      网友评论

      • a2817a9f7cc7:感谢感谢,简洁明了
      • b8b659c46c22:你好。“Positional arguments:”的例子里args.foo是不是写错了,应该是args.echo吧?
        Edward_f0cus:已更正,多谢
      • 双桐:在各种英文材料里挣扎了好久都没弄懂,看了这一篇就全清楚了~~太感谢了!!
      • 52c9018b6e44:写的非常易懂!感谢!
        Edward_f0cus:my pleasure:)

      本文标题:argparser模块学习

      本文链接:https://www.haomeiwen.com/subject/jsnfkttx.html