Python命令行参数解析之argparse模块详解
一、argparse是什么?
argparse 是 Python 的一个标准库,用于命令行参数的解析,argparse 模块可以让人轻松编写用户友好的命令行接口,这意味着我们无需在代码中手动为变量赋值,而是可以直接在命令行中向程序传递相应的参数,再由变量去读取这些参数。
argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。
如果没有安装 argparse,可执行如下命令进行安装
|
1
|
pip install argparse |
使用时只需导入
|
1
|
import argparse |
1.1 一个例子
我们先来看一个最简单的例子,了解了使用 argparse 的大致步骤后,再来详细介绍各个API。
|
1
2
3
4
5
6
7
8
|
""" 求解两数之和 """twoSum = lambda x, y: x + yparser = 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.bprint(twoSum(first_num, second_num)) |
将以上内容保存到 demo.py 中。我们先在命令行执行
|
1
|
python3 demo.py -h |
可以看到相应的帮助信息
|
1
2
3
4
5
|
usage: demo.py [-h] --a A --b Boptions: -h, --help show this help message and exit --a A first number --b B second number |
从 usage 可以看出 demo.py 接收两个必选项:--a 和 --b(带有 [] 的为可选项,没带的为必选项),它们分别代表第一个数和第二个数,其中 A 和 B 分别代表实际传入的参数。
在命令行中执行
|
1
|
python3 demo.py --a 12 --b 19 |
返回结果是 31,这说明我们通过命令行完成了求解两数之和这个操作。
二、ArgumentParser
使用 argparse 的第一步是先创建一个 ArgumentParser 对象,该对象包含将命令行解析成 Python 数据类型所需的全部信息,其常用参数如下
|
1
|
argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None) |
2.1 prog
prog 默认值为 os.path.basename(sys.argv[0]),也就是程序所在文件的名称。
例如在第一章节中,我们在创建 ArgumentParser 对象时没有指定 prog,因此采用了默认值 demo.py。
先来看一个例子
|
1
2
|
parser = argparse.ArgumentParser()parser.print_help() # 和在命令行调用 python3 demo.py -h 的效果一样(会有一些细微差别) |
输出的帮助信息:
|
1
2
3
|
usage: demo.py [-h]options: -h, --help show this help message and exit |
可以看到若不指定 prog,则帮助信息将显示 demo.py 作为程序名称。现在指定 prog
|
1
|
parser = argparse.ArgumentParser(prog="My Program") |
相应的帮助信息:
|
1
2
3
|
usage: My Program [-h]options: -h, --help show this help message and exit |
可以看到原先 demo.py 的地方变成了 My Program。
2.2 usage
默认情况下,ArgumentParser 根据它包含的选项来构建用法消息。
这里依然使用第一章节的例子:
|
1
2
3
4
5
|
usage: demo.py [-h] --a A --b Boptions: -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
|
1
|
parser = argparse.ArgumentParser(usage="See the options below for usage") |
相应的帮助信息变成
|
1
2
3
4
5
|
usage: See the options below for usageoptions: -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
|
1
|
parser = argparse.ArgumentParser(description="This is my program.") |
相应的帮助信息
|
1
2
3
4
5
6
|
usage: demo.py [-h] --a A --b BThis 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
|
1
|
parser = argparse.ArgumentParser(description="This is my program.", epilog="The end.") |
相应的帮助信息
|
1
2
3
4
5
6
7
|
usage: demo.py [-h] --a A --b BThis is my program.options: -h, --help show this help message and exit --a A first number --b B second numberThe end. |
通常来讲,以上四个参数中用的最多的是
prog
三、add_argument
add_argument() 方法用于向解析器中添加一个选项(位置参数)。
|
1
2
3
4
5
6
7
8
9
|
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。
例如
|
1
2
3
|
parser = argparse.ArgumentParser()parser.add_argument('-i', '--install')args = parser.parse_args() |
相应的帮助信息:
|
1
2
3
4
|
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 是等价的。
与选项不同的是,位置参数前不能加 -,并且每次只能传入一个,例如
|
1
2
3
4
|
parser = argparse.ArgumentParser()parser.add_argument('param1')parser.add_argument('param2')args = parser.parse_args() |
相应的帮助信息:
|
1
2
3
4
5
|
usage: demo.py [-h] param1 param2positional arguments: integeroptions: -h, --help show this help message and exit |
从 usage 可以看出位置参数在调用命令行时是必须传入的。
以上是先添加位置参数 param1 再添加 param2 的,如果我们调换顺序,则帮助信息中的两个参数的位置也将调换,这也诠释了 “位置” 的含义。
可以看出,选项和位置参数,前者相当于关键字传参,后者相当于位置传参。
3.2 type & default
顾名思义,type 指选项或位置参数将要被转换成的数据类型(在命令行中传入的参数都默认以 str 类型存在)。
例如
|
1
2
3
4
5
|
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 指选项或位置参数的默认值,例如
|
1
2
3
4
|
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。
例如
|
1
2
3
|
parser = argparse.ArgumentParser()parser.add_argument('--a')args = parser.parse_args() |
此时帮助信息为
|
1
2
3
4
|
usage: demo.py [-h] [--a A]options: -h, --help show this help message and exit --a A |
usage 一行中 --a A 被一对方括号 [] 括了起来,说明 --a 是可选项。现在指定 required=True
|
1
|
parser.add_argument('--a', required=True) |
这时候帮助信息变为
|
1
2
3
4
|
usage: demo.py [-h] --a Aoptions: -h, --help show this help message and exit --a A |
可以看到 [] 消失了,说明 --a 变成了必选项。
help 用来描述一个选项或位置参数,该描述将会显示在帮助信息中
|
1
2
3
|
parser = argparse.ArgumentParser()parser.add_argument('--lr', type=float, default=1e-3, help="learning rate")args = parser.parse_args() |
相应的帮助信息
|
1
2
3
4
|
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 来指定
|
1
2
3
4
|
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 来指定一个列表
|
1
2
3
|
parser = argparse.ArgumentParser()parser.add_argument('--a', type=int, choices=[1, 3, 5])args = parser.parse_args() |
相应的帮助信息
|
1
2
3
4
|
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
我们先来看一个例子。
|
1
2
3
4
5
6
|
import argparseimport sysparser = 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:] 作为其参数,并返回一个命名空间(类似于字典)。
举个例子
|
1
2
3
4
5
6
7
|
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() 这一步中,可能会出现报错情况,例如
|
1
2
3
|
parser = argparse.ArgumentParser()parser.add_argument('--a', type=int)args = parser.parse_args() |
如果我们在命令行执行 python3 demo.py --a 'abc' 就会报错,这是因为字符串无法转换成整数。
|
1
2
|
usage: demo.py [-h] [--a A]demo.py: error: argument --a: invalid int value: 'abc' |
一般我们会采用如下代码块来避免直接看到不友好的报错
|
1
2
3
4
5
|
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 中的内容为
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import argparseimport 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.bsLEARNING_RATE = args.lr# 其他代码... |
这时候我们只需要在脚本目录 scripts 下新建一个文件 train.sh,向其中写入内容
|
1
2
3
4
5
|
# 用来确保无论在哪里执行该脚本,都能够正确返回该脚本所在的目录,以便后续根据这个目录来定位所要运行程序的相对位置cd "$(dirname $0)"python3 ../train.py \--bs 256 \--lr 0.005 \ |
然后在命令行执行(假设当前处于 myproject 目录下)
|
1
|
cd scripts && bash train.sh |
即可开始训练,后续如果需要调参,修改
train.sh 里的数字即可。Python parser.add_argument函数及sys.argv[]
1.Python解析参数
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import argparseparser = argparse.ArgumentParser(description = 'TEST')parser.add_argument ('--start-epoch', default = 0, type = int, help = 'please input number')def main(): global args args = parser.parse_args() print(args) print(args.start_epoch)if __name__ == '__main__': main() |
注:在参数解析时,参数中并不区分字符‘-’和‘_’;如上所述,在添加是使用的是’–start-epoch’,但是在解析时使用的是args.start_epoch。
2.parser.add_argument参数action
在使用parser进行传参时,遇到参数action,一直不得其解,终有所获,解释如下:
|
1
|
parser.add_argument(‘--is_train', action='store_true', default=False) |
其中“–is_train”参数在调用时,如下:
|
1
2
3
|
python demo1.py #无参数传入时,使用默认值False python demo1.py --is_train #当使用此参数时,表示该参数是True, 注意在这里并没有对其赋值, #其作用是作为开关使用,来控制action动作 |
3.步骤
1、创建一个解析器——创建 ArgumentParser() 对象
|
1
|
parser = argparse.ArgumentParser(description='PyTorch ImageNet Training') |
变量名为parser,ArgumentParser 对象包含将命令行解析成 Python 数据类型所需的全部信息。
关键词description:这个参数简要描述这个程度做什么以及怎么做。在帮助消息中,这个描述会显示在命令行用法字符串和各种参数的帮助消息之间。
2、添加参数——调用 add_argument() 方法添加参数
调用 add_argument() 给程序添加参数信息。这些调用指定 ArgumentParser 如何获取命令行字符串并将其转换为对象。
常用的有,
|
1
2
3
4
5
6
7
|
parser.add_argument('data', metavar='DIR',help='path to dataset') # 设置数据路径parser.add_argument('--epochs', default=200, type=int, metavar='N', # 训练循环最高次数 help='number of total epochs to run')parser.add_argument('--lr', '--learning-rate', default=0.03, type=float, # 学习率 metavar='LR', help='initial learning rate', dest='lr')parser.add_argument('--seed', default=None, type=int, help='seed for initializing training. ') # 用于指定随机数生成时所用算法开始的整数值 |
3、解析参数——使用 parse_args() 解析添加的参数
ArgumentParser 通过 parse_args() 方法解析参数。它将检查命令行,把每个参数转换为适当的类型然后调用相应的操作。
在大多数情况下,这意味着一个简单的 Namespace 对象将从命令行解析出的属性构建。
|
1
|
args = parser.parse_args() |
4.add_argument() 命令行参数
|
1
|
ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest]) |
每个参数解释如下:
name or flags- 选项字符串的名字或者列表,例如 foo 或者 -f, --foo。action- 命令行遇到参数时的动作,默认值是 store。store_const,表示赋值为const;append,将遇到的值存储成列表,也就是如果参数重复则会保存多个值;append_const,将参数规范中定义的一个值保存到一个列表;count,存储遇到的次数;此外,也可以继承 argparse.Action 自定义参数解析;nargs- 应该读取的命令行参数个数,可以是具体的数字,或者是?号,当不指定值时对于 Positional argument 使用 default,对于 Optional argument 使用 const;或者是 * 号,表示 0 或多个参数;或者是 + 号表示 1 或多个参数。default- 不指定参数时的默认值。type- 命令行参数应该被转换成的类型。choices- 参数可允许的值的一个容器。required- 可选参数是否可以省略 (仅针对可选参数)。help- 参数的帮助信息,当指定为 argparse.SUPPRESS 时表示不显示该参数的帮助信息.metavar- 在 usage 说明中的参数名称,对于必选参数默认就是参数名称,对于可选参数默认是全大写的参数名称。用来控制部分命令行参数的显示,注意:它只是影响部分参数的显示信息,不影响代码内部获取命令行参数的对象。dest- 解析后的参数名称,默认情况下,对于可选参数选取最长的名称,中划线转换为下划线.
4.sys.argv[]
是一个从程序外部获取参数的桥梁,获得的是一个列表(list),其第一个元素是程序本身,随后才依次是外部给予的参数。
|
1
|
sys.argv[0] # 对应的是程序本身,即xxx.py,xxx表示程序的名称。 |
|
1
|
sys.argv[1表示命令行外部输入的第一个参数。 |
|
1
|
sys.argv[1:] # 表示遍历外部输入参数的所有 |

浙公网安备 33010602011771号