前言:阅读源码时遇到argparse库,我为了理解用法找了不少博客,要么晦涩难懂,要么讲的太浅。最后还是看了官方英文教程,讲得非常清楚。本文大部分内容都来源于官方教程,我做了小小的翻译和整理工作,为英文不太好的同学节省一下时间。这篇文章略长,但我相信只要你从头读到尾,一定可以很好地理解argparse的用法。
转载请注明出处哦
我们在写python程序的时候,有时候希望在执行的时候附加一些参数。为了在程序中使用这些附加参数,我们需要正确地解析它们,这个时候argparse就派上用场了,argparse是一款简单而又强大的命令行解析工具。
首先,让我们看看Linux中常用的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
命令不加任何附加参数的时候就非常有用,它默认会展示当前文件夹里的内容cp
命令,基础的使用方法是cp SRC DEST
,第一个位置是想要复制的文件,第二个位置是想要复制到的地方。-l
做了这件事,它被称为可选参数让我们从一个简单到几乎什么也不做的例子,来开始argparse的学习:
# prog.py
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
下面是我们从命令行运行代码的结果:
$ python3 prog.py
$ python3 prog.py --help
usage: prog.py [-h]
optional arguments:
-h, --help show this help message and exit
$ python3 prog.py --verbose
usage: prog.py [-h]
prog.py: error: unrecognized arguments: --verbose
$ python3 prog.py foo
usage: prog.py [-h]
prog.py: error: unrecognized arguments: foo
观察上面的代码和执行过程,你能发现什么呢?
--help
就可以展示它--help
参数也可以用更简短的-h
来替代,它们是argparse唯一的免费参数,哈哈,之所以说是免费,是因为我们无需在程序中定义它们的行为就拥有了它们,观察prog.py,并没有任何和--help
相关的代码。但是,除了--help
,-h
之外,指定任何其他的附加参数都会报错,因为我们没有在程序中定义它们。接下来我会介绍如何定义自己的参数。看这个例子:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print(args.echo)
命令行执行代码:
$ python3 prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo
$ python3 prog.py --help
usage: prog.py [-h] echo
positional arguments:
echo
optional arguments:
-h, --help show this help message and exit
$ python3 prog.py foo
foo
观察上面的代码和执行过程,你发现了什么呢?
add_argument
函数,这个函数允许我们指定自己的命令行参数。在这个例子中,我指定了一个名叫echo
的参数the following arguments are required: echo
parse_args()
会返回用户给出的参数值,在这个例子中,是echo
参数的值。parse_args()
返回的参数的值可以通过 .参数名
获得,这个例子里,我们通过args.echo
就可以得到echo
的参数值,是我们传的字符串‘foo‘。注意,这个参数名就是我们在add_argument
函数里给出的字符串‘echo‘。--help
输出的帮助文档,虽然看起来已经很不错了,但是并不是很有帮助。比如,通过帮助文档,我们知道echo
是一个位置参数,但是并不知道它是什么,除了看prog.py的源代码我们根本不知道这个参数的作用是啥。所以,来让它更有用吧:import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print(args.echo)
然后我们就会看到:
$ python3 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)
上面的程序功能是从命令行读取一个位置参数square,然后打印它的平方值。
看看执行过程:
$ python3 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应该将输入视作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)
然后执行代码:
$ python3 prog.py 4
16
$ python3 prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: ‘four‘
哇,很完美有没有,程序现在可以很好地运作了。而且你发现没,当我们输入four作为参数时,这不是一个数字,如果不使用argparse,我们要到运算平方的时候才报类型错误,现在在参数解析的时候程序就会因为类型不匹配提前退出,很棒吧。
到目前为止我们一直在和位置参数打交道,让我们看看怎么添加可选参数吧!
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
print("verbosity turned on")
执行程序:
$ python3 prog.py --verbosity 1
verbosity turned on
$ python3 prog.py
$ python3 prog.py --help
usage: prog.py [-h] [--verbosity VERBOSITY]
optional arguments:
-h, --help show this help message and exit
--verbosity VERBOSITY
increase output verbosity
$ python3 prog.py --verbosity
usage: prog.py [-h] [--verbosity VERBOSITY]
prog.py: error: argument --verbosity: expected one argument
观察上面的代码和执行过程,你发现了什么呢?
--
上面的例子中,我们需要接受一个任意值给--verbosity。但实际上,我们希望指定--verbosity时,args.verbosity为True,不指定为False就够了。能不能不指定一个值给--verbosity呢?看看这个例子
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")
然后执行:
$ python3 prog.py --verbose
verbosity turned on
$ python3 prog.py --verbose 1
usage: prog.py [-h] [--verbose]
prog.py: error: unrecognized arguments: 1
$ python3 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"
,这意味着,如果执行程序时指定了--verbose标志,就把True
赋给args.verbose
,如果没有指定,就把False
赋给它如果你熟悉命令行的操作,你就会注意到,截至目前,我还没有讨论简短参数。什么是简短参数呢?比如--help
,可以用-h
代替,一个横杠开头的-h
就是简短参数。其实定义简短参数非常简单:
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")
然后就会这样:
$ python3 prog.py -v
verbosity turned on
$ python3 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)
执行代码:
$ python3 prog.py
usage: prog.py [-h] [-v] square
prog.py: error: the following arguments are required: square
$ python3 prog.py 4
16
$ python3 prog.py 4 --verbose
the square of 4 equals 16
$ python3 prog.py --verbose 4
the square of 4 equals 16
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)
看出区别了吗,我们把--verbosity的type设成了int,并且把action=‘store_true‘去掉了。这样就要指定一个数字给它。
执行代码:
$ python3 prog.py 4
16
$ python3 prog.py 4 -v
usage: prog.py [-h] [-v VERBOSITY] square
prog.py: error: argument -v/--verbosity: expected one argument
$ python3 prog.py 4 -v 1
4^2 == 16
$ python3 prog.py 4 -v 2
the square of 4 equals 16
$ python3 prog.py 4 -v 3
16
看起来很不错!除了最后一个,我们不希望赋3给verbosity时它反而输出一个更短的句子,这是我们程序中的一个bug。让我们来修复这个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)
执行一下代码:
$ python3 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)
$ python3 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”,去计算选项被指定的次数。看下面的执行过程你就懂了:
$ python3 prog.py 4
16
$ python3 prog.py 4 -v
4^2 == 16
$ python3 prog.py 4 -vv
the square of 4 equals 16
$ python3 prog.py 4 --verbosity --verbosity
the square of 4 equals 16
$ python3 prog.py 4 -v 1
usage: prog.py [-h] [-v] square
prog.py: error: unrecognized arguments: 1
$ python3 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
$ python3 prog.py 4 -vvv
16
action=‘store_true‘
有点类似),当你给--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", 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)
然后执行:
$ python3 prog.py 4 -vvv
the square of 4 equals 16
$ python3 prog.py 4 -vvvv
the square of 4 equals 16
$ python3 prog.py 4
Traceback (most recent call last):
File "prog.py", line 11, in <module>
if args.verbosity >= 2:
TypeError: ‘>=‘ not supported between instances of ‘NoneType‘ and ‘int‘
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
,我们将它设为0,这样在不指定-v时,args.verbosity被设为0,就可以和其他数字比较了!记住,如果某个可选参数在执行时没有被指定,就会赋None值给它,而None是无法和int值做比较的!解决办法就是给它一个defualt值。
现在:
$ python3 prog.py 4
16
根据上面所学的知识,你已经可以做非常非常多的事了,但实际上我们也只涉及到argparse强大功能的表面而已。argparse非常强大,如果有需要,大伙可以查阅argparse的官方api文档。
码字不易,如果觉得文章不错的话,点个赞再走吧,秋梨膏!
原文:https://www.cnblogs.com/mmxy/p/13779761.html