Python命令行参数解析之argparse模块详解
作者:Iareges
一、argparse是什么?
argparse
是 Python 的一个标准库,用于命令行参数的解析,这意味着我们无需在代码中手动为变量赋值
而是可以直接在命令行中向程序传递相应的参数,再由变量去读取这些参数。
如果没有安装 argparse
,可执行如下命令进行安装
pip install argparse
使用时只需导入
import argparse
1.1 一个例子
我们先来看一个最简单的例子,了解了使用 argparse
的大致步骤后,再来详细介绍各个API。
""" 求解两数之和 """ twoSum = lambda x, y: x + y parser = argparse.ArgumentParser() parser.add_argument('--a', type=int, required=True, help="first number") parser.add_argument('--b', type=int, required=True, help="second number") args = parser.parse_args() first_num, second_num = args.a, args.b print(twoSum(first_num, second_num))
将以上内容保存到 demo.py
中。我们先在命令行执行
python3 demo.py -h
可以看到相应的帮助信息
usage: demo.py [-h] --a A --b B options: -h, --help show this help message and exit --a A first number --b B second number
从 usage
可以看出 demo.py
接收两个必选项:--a
和 --b
(带有 []
的为可选项,没带的为必选项),它们分别代表第一个数和第二个数,其中 A
和 B
分别代表实际传入的参数。
在命令行中执行
python3 demo.py --a 12 --b 19
返回结果是 31
,这说明我们通过命令行完成了求解两数之和这个操作。
二、ArgumentParser
使用 argparse
的第一步是先创建一个 ArgumentParser
对象,该对象包含将命令行解析成 Python 数据类型所需的全部信息,其常用参数如下
argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None)
2.1 prog
prog
默认值为 os.path.basename(sys.argv[0])
,也就是程序所在文件的名称。
例如在第一章节中,我们在创建 ArgumentParser
对象时没有指定 prog
,因此采用了默认值 demo.py
。
先来看一个例子
parser = argparse.ArgumentParser() parser.print_help() # 和在命令行调用 python3 demo.py -h 的效果一样(会有一些细微差别)
输出的帮助信息:
usage: demo.py [-h] options: -h, --help show this help message and exit
可以看到若不指定 prog
,则帮助信息将显示 demo.py
作为程序名称。现在指定 prog
parser = argparse.ArgumentParser(prog="My Program")
相应的帮助信息:
usage: My Program [-h] options: -h, --help show this help message and exit
可以看到原先 demo.py
的地方变成了 My Program
。
2.2 usage
默认情况下,ArgumentParser
根据它包含的选项来构建用法消息。
这里依然使用第一章节的例子:
usage: demo.py [-h] --a A --b B options: -h, --help show this help message and exit --a A first number --b B second number
因为我们没有指定 usage
,所以 ArgumentParser
将使用它包含的三个选项:-h
、--a
、--b
来构建用法消息 usage
,它位于帮助信息的第一行。
如果觉得默认的 usage
有些冗余(因为下方的 options
已经详细介绍了各个选项),我们可以自定义 usage
parser = argparse.ArgumentParser(usage="See the options below for usage")
相应的帮助信息变成
usage: See the options below for usage options: -h, --help show this help message and exit --a A first number --b B second number
需要注意的是,在指定了 usage
后,prog
将会被覆盖,即使在 ArgumentParser
中指定了 prog
也没有用。
2.3 description
description
参数用来简要描述这个程序做什么以及怎么做。不指定 description
时,帮助信息中将不予显示。
依然使用第一章节的例子,这里我们指定 description
parser = argparse.ArgumentParser(description="This is my program.")
相应的帮助信息
usage: demo.py [-h] --a A --b B This is my program. options: -h, --help show this help message and exit --a A first number --b B second number
可以看到 usage
和 options
中间多了一行内容,这就是我们指定的 description
。
2.4 epilog
该参数和 description
类似,区别在于,description
放在了 options
之前,而 epilog
放在了 options
之后。
依然使用第一章节的例子,这里我们同时指定 description
和 epilog
parser = argparse.ArgumentParser(description="This is my program.", epilog="The end.")
相应的帮助信息
usage: demo.py [-h] --a A --b B This is my program. options: -h, --help show this help message and exit --a A first number --b B second number The end.
通常来讲,以上四个参数中用的最多的是
prog
三、add_argument
add_argument()
方法用于向解析器中添加一个选项(位置参数)。
ArgumentParser.add_argument( name or flags..., nargs, default, type, choices, required, help )
以上仅列出了 add_argument()
方法中最常用的几个参数。
3.1 name or flags
name or flags
为选项(options
)或位置参数(positional arguments
)。
如果是选项的话可以传入一系列flags(例如自带的帮助就有两个:-h
、--help
),如果是位置参数的话则只能传入一个 name
。
例如
parser = argparse.ArgumentParser() parser.add_argument('-i', '--install') args = parser.parse_args()
相应的帮助信息:
usage: demo.py [-h] [-i INSTALL] options: -h, --help show this help message and exit -i INSTALL, --install INSTALL
这意味着我们在命令行调用 python3 demo.py -i INSTALL
和 python3 demo.py --install INSTALL
是等价的。
与选项不同的是,位置参数前不能加 -
,并且每次只能传入一个,例如
parser = argparse.ArgumentParser() parser.add_argument('param1') parser.add_argument('param2') args = parser.parse_args()
相应的帮助信息:
usage: demo.py [-h] param1 param2 positional arguments: integer options: -h, --help show this help message and exit
从 usage
可以看出位置参数在调用命令行时是必须传入的。
以上是先添加位置参数 param1
再添加 param2
的,如果我们调换顺序,则帮助信息中的两个参数的位置也将调换,这也诠释了 “位置” 的含义。
可以看出,选项和位置参数,前者相当于关键字传参,后者相当于位置传参。
3.2 type & default
顾名思义,type
指选项或位置参数将要被转换成的数据类型(在命令行中传入的参数都默认以 str
类型存在)。
例如
parser = argparse.ArgumentParser() parser.add_argument('--a') parser.add_argument('--b', type=int) args = parser.parse_args() print(type(args.a), type(args.b))
执行 python3 demo.py --a 3 --b 3
后得到结果
<class 'str'> <class 'int'>
default
指选项或位置参数的默认值,例如
parser = argparse.ArgumentParser() parser.add_argument('--a', type=int, default=5) args = parser.parse_args() print(args.a)
直接执行 python3 demo.py
将会输出 5
,因为采用了默认值。
如果执行 python3 demo.py --a x
则会输出 x
(x
是任何整数,且不能省略)。
如果没有为
--a
指定默认值,且在命令行执行时也没有向--a
传参,则args.a
为None
。
3.3 required & help
因为位置参数在命令行中是必须传入的,所以 required
只能用于选项。
required
设为 True
则代表此选项为必选项,否则为可选项,默认为 False
。
例如
parser = argparse.ArgumentParser() parser.add_argument('--a') args = parser.parse_args()
此时帮助信息为
usage: demo.py [-h] [--a A] options: -h, --help show this help message and exit --a A
usage
一行中 --a A
被一对方括号 []
括了起来,说明 --a
是可选项。现在指定 required=True
parser.add_argument('--a', required=True)
这时候帮助信息变为
usage: demo.py [-h] --a A options: -h, --help show this help message and exit --a A
可以看到 []
消失了,说明 --a
变成了必选项。
help
用来描述一个选项或位置参数,该描述将会显示在帮助信息中
parser = argparse.ArgumentParser() parser.add_argument('--lr', type=float, default=1e-3, help="learning rate") args = parser.parse_args()
相应的帮助信息
usage: demo.py [-h] [--lr LR] options: -h, --help show this help message and exit --lr LR learning rate
3.4 nargs & choices
假如选项 --a
需要接收5个参数,此时需要用 nargs
来指定
parser = argparse.ArgumentParser() parser.add_argument('--a', type=int, nargs=5) args = parser.parse_args() print(args.a)
执行 python3 demo.py --a 1 2 3 4 5
可以得到
[1, 2, 3, 4, 5]
需要注意,nargs=1
最终会得到一个只含一个元素的列表,而非元素本身。
更进一步,nargs='?'
代表传入参数的数量为0个或1个,nargs='+'
代表传入参数的数量至少1个,nargs='*'
代表可传入任意多的参数。
有些时候,选项 --a
的取值只能是固定的几种,例如 --a
只能从整数1,3,5中选取,这时候需要用 choices
来指定一个列表
parser = argparse.ArgumentParser() parser.add_argument('--a', type=int, choices=[1, 3, 5]) args = parser.parse_args()
相应的帮助信息
usage: demo.py [-h] [--a {1,3,5}] options: -h, --help show this help message and exit --a {1,3,5}
如果 --a
后面跟的数字不是1,3,5中的一个就会报错。
四、parse_args
我们先来看一个例子。
import argparse import sys parser = argparse.ArgumentParser() parser.add_argument('--a', type=int) parser.add_argument('--b', type=int) print(sys.argv)
在命令行执行 python3 demo.py --a 3 --b 5
得到结果
['demo.py', '--a', '3', '--b', '5']
从中可以看出,sys.argv[0]
是文件名,sys.argv[1:]
是我们在命令行中传入的选项。
在之前的学习过程中,可能你已经注意到了,每次我们为解析器添加完相应的选项/位置参数后,都要执行一遍 parser.parse_args()
。
默认情况下,parse_args()
采用 sys.argv[1:]
作为其参数,并返回一个命名空间(类似于字典)。
举个例子
parser = argparse.ArgumentParser() parser.add_argument('--a', type=int, nargs=3) parser.add_argument('--b', type=str) parser.add_argument('--c', type=float) args = parser.parse_args() print(type(args)) print(args)
执行 python3 demo.py --a 1 3 5 --b 'k' --c 3.14
得到
<class 'argparse.Namespace'>
Namespace(a=[1, 3, 5], b='k', c=3.14)
如果只执行 python3 demo.py --a 1 3 5 --b 'k'
,则得到
<class 'argparse.Namespace'>
Namespace(a=[1, 3, 5], b='k', c=None)
可以看出,如果在命令行中没有提供相应的选项,并且该选项也没有默认值,则在命名空间中该选项的值为 None
,这一点我们早在 3.2 节中就已经提到了。
parser.parse_args()
返回的是一个命名空间对象,我们通常用 args
来存储。
要访问 args
中键 k
对应的值 v
,只需要 args.k
即可。
五、避免报错
在执行 args = parser.parse_args()
这一步中,可能会出现报错情况,例如
parser = argparse.ArgumentParser() parser.add_argument('--a', type=int) args = parser.parse_args()
如果我们在命令行执行 python3 demo.py --a 'abc'
就会报错,这是因为字符串无法转换成整数。
usage: demo.py [-h] [--a A] demo.py: error: argument --a: invalid int value: 'abc'
一般我们会采用如下代码块来避免直接看到不友好的报错
try: args = parser.parse_args() except: parser.print_help() sys.exit(0)
六、使用shell脚本进行调参
深度学习经常需要调参,如果直接使用IDE打开 .py
文件去调未免显得有些笨拙,而且也会变得不好维护。
如果使用 argparse
,虽然不用每次修改 .py
文件,但在命令行里反复修改也略显麻烦,这时候就需要将其与shell脚本进行结合了。
为简便起见,假设我们的项目架构如下:
myproject
├── __init__.py
├── model
│ ├── model1.py
│ ├── model2.py
│ └── model3.py
├── scripts
│ └── train.sh
├── train.py
└── utils
├── utils1.py
└── utils2.py
其中 train.py
中的内容为
import argparse import sys # 导入其他的包... # 假设只有两个超参数需要调 parser = argparse.ArgumentParser() parser.add_argument('--bs', type=int, default=128, help="batch size") parser.add_argument('--lr', type=float, default=0.001, help="learning rate") try: args = parser.parse_args() except: parser.print_help() sys.exit(0) # 超参数设置 BATCH_SIZE = args.bs LEARNING_RATE = args.lr # 其他代码...
这时候我们只需要在脚本目录 scripts
下新建一个文件 train.sh
,向其中写入内容
# 用来确保无论在哪里执行该脚本,都能够正确返回该脚本所在的目录,以便后续根据这个目录来定位所要运行程序的相对位置 cd "$(dirname $0)" python3 ../train.py \ --bs 256 \ --lr 0.005 \
然后在命令行执行(假设当前处于 myproject
目录下)
cd scripts && bash train.sh
即可开始训练。后续如果需要调参,修改 train.sh
里的数字即可。
到此这篇关于Python命令行参数解析之argparse模块详解的文章就介绍到这了,更多相关Python的argparse模块内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!