经常用的模块, 也是老用老忘, 用一次学一次. 写篇blog, 加深印象. refer to: python howto
argument和parameter的区别: 其实跟今天的主题没多大关系, 顺便说一下, 因为看一些英文的技术文章, 会经常用这两个概念. parameter就相当于java里的”形参”:方法/函数定义时在括号里的参数
1 2 def explain_param_vs_arg (param1, param2) : print param1, param2
argument就是所谓”实参”:调用方法/函数时括号里的参数
1 explain_param_vs_arg("arg1" , "arg2" )
Positional arguments: 例子:
1 2 3 4 5 import argparseparser = 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 $ 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
上面的例子,基本没什么用. 来个有用点的:
1 2 3 4 5 import argparseparser = 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
加了help参数之后, -h就加了对echo这个参数的说明. 来个更有用点的:
1 2 3 4 5 import argparseparser = 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 , in <module > print args.square **2 TypeError: unsupported operand type (s) for ** or pow (): 'str' and 'int'
结果不太理想. 是因为argparse把我们给的参数认成了string. 我们得告诉TA把square当成int来处理:
1 2 3 4 5 6 import argparseparser = 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'
这把就对了. 如果参数非法了还会报错.
Optional arguments 前面介绍了positional arguments. 接下来我们看看optional arguments:
1 2 3 4 5 6 import argparseparser = 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 $ 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. 我们改一下:
1 2 3 4 5 6 7 import argparseparser = 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 $ 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. 实现起来其实非常简单.
1 2 3 4 5 6 7 import argparseparser = 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 $ 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 让代码来的更复杂点吧:
1 2 3 4 5 6 7 8 9 10 11 12 import argparseparser = 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 $ 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也带回来:
1 2 3 4 5 6 7 8 9 10 11 12 import argparseparser = 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 $ 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它:
1 2 3 4 5 6 7 8 9 10 11 12 13 import argparseparser = 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 $ 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):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import argparseparser = 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的出现次数.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 $ 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一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import argparseparser = 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 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 $ 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import argparseparser = 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
. 是不能跟数字做比较的.
目前介绍的功能已经能应付很多情况了. 在结束之前, 我们再来点更猛的吧.
更高级的用法 我们扩展一下这个例子, 来显示更多内容:
1 2 3 4 5 6 7 8 9 10 11 12 import argparseparser = 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
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ 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
. 它们是互斥的关系. 我们可以这么实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import argparseparser = 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 $ 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
最后, 如果你想告诉用户程序的主要目的. 可以这么来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import argparseparser = 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 $ 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