Python经常被用来写一下简化操作的脚本,并且要求脚本支持一定的选项,有必要整理一下Python命令行参数解析的用法。

Python自带的argparse模块功能已经非常强大,使用非常便捷。 Python其实还有另外两个模块可以完成同样的任务:getoptoptparse,但是前者过于简单,后者已经被弃用,目前只推荐使用argparse

与之形成鲜明对比的是,C++对这种基础的需求通常都是直接手写的,或者去下载一些第三方提供的纯头文件库,为这种简单的任务引入外部依赖其实也并不合算,不如直接自己写了。

极简例子

从最简单的例子开始

test.py
1
2
3
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

这两行的含义为:设置一个参数解析器,解析参数。

直接运行脚本,无事发生

1
python test.py

空的参数解析器为我们提供了--help-h)参数,可以打印使用帮助,例如

1
python test.py -h

输出形如

1
2
3
4
usage: test.py [-h]

options:
-h, --help show this help message and exit

基本使用

位置参数

我们可以添加位置参数,例如

test.py
1
2
3
4
5
6
7
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("op1")
parser.add_argument("op2")
args = parser.parse_args()
print("op1 =", args.op1)
print("op2 =", args.op2)

这里我们直接使用了args.op1,这是argparse直接提供的“魔法”:args的成员名称由add_argument传入的字符串决定。 我们从args得到的也只是字符串,如果需要作为其它数据类型使用,需要手动进行类型转换。

使用例如

test.py
1
python test.py value1 value2

输出

1
2
op1 = value1
op2 = value2

在加入了两个位置参数之后,使用帮助变成了

1
2
3
4
5
6
7
8
usage: test.py [-h] op1 op2

positional arguments:
op1
op2

options:
-h, --help show this help message and exit

我们可以给选项加上描述

test.py
1
2
3
4
5
6
7
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("op1", help="op1 is xxx")
parser.add_argument("op2", help="op2 is yyy")
args = parser.parse_args()
print("op1 =", args.op1)
print("op2 =", args.op2)

这可以提升使用帮助的可读性

1
2
3
4
5
6
7
8
usage: test.py [-h] op1 op2

positional arguments:
op1 op1 is xxx
op2 op2 is yyy

options:
-h, --help show this help message and exit

可选参数

我们可以为脚本添加可选参数(必须以---开头),例如

test.py
1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--config", help="set config file")
args = parser.parse_args()
if args.config:
print("config is", args.config)

注意这里我们仍然通过args.config获取对应的值。

使用例如

1
python test.py --config abc

我们也可以不提供可选参数

1
python test.py

但是如果我们使用了--config,却在后面不提供值,就会报错

1
2
usage: test.py [-h] [--config CONFIG]
test.py: error: argument --config: expected one argument

对于可选参数,我们可以选择支持长参数或短参数形式,或者同时使用两者,例如

test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-c", "--config", help="set config file")
parser.add_argument("-v", help="set value")
parser.add_argument("--file", help="set file")
args = parser.parse_args()
if args.config:
print("config is", args.config)

if args.v:
print("value is", args.v)

if args.file:
print("file is", args.file)

如果同时支持长参数和短参数,需要通过长参数形式来获取选项的结果。

开关参数

前面的可选参数在提供选项时必须要提供对应的值,但有时候我们只关注有没有这个参数选项,起到开关作用, 可以使用action="store_true"实现:

  • 如果提供了选项,对应的值自动设置为true
  • 如果没有提供选项,对应的值自动设置为false

与之相反的是action="store_false",解析器并不会将选项后面的内容视作选项的值。

test.py
1
2
3
4
5
6
7
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")

使用例如

1
python test.py --verbose

更多细节

丰富帮助信息

我们可以在定义解析器时,传入程序名称和描述信息,它们会显示在帮助信息中

1
2
3
4
parser = argparse.ArgumentParser(
prog='ProgramName',
description='What the program does',
epilog='Text at the bottom of help')

其中prog缺省时会自动使用脚本名称(会自动移除路径部分),description是对程序的描述,epilog是帮助信息最后的结束语,两者默认为空。

通常情况下,解析器会根据选项要求自动生成使用示例,我们也可以通过usage参数指定

1
parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')

参数类型限制

例如

test.py
1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

可选参数默认值

例如

test.py
1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--config", default="config.ini", help="set config file")
args = parser.parse_args()
if args.config:
print("config is", args.config)

必需参数

例如

test.py
1
2
3
4
5
6
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--config", required=True, help="set config file")
args = parser.parse_args()
if args.config:
print("config is", args.config)

注意必需的优先级比默认值更高,如果设置为必需,那么提供的默认值实际上不起作用。

参数重复计数

我们可以支持重复某个选项多次,例如-v-vv,后者将提供更详细的信息。

例如

test.py
1
2
3
4
5
6
7
8
9
10
import argparse

parser = argparse.ArgumentParser()
parser.add_argument(
"-v", "--verbosity", action="count", help="increase output verbosity"
)
args = parser.parse_args()

if args.verbosity:
print("verbosity turned on: {}".format(args.verbosity))

这里action="count"代表对选项出现次数计数。 注意:如果不对这个选项设置default=0,那么默认值会是None

使用例如

1
2
3
4
5
6
7
8
9
10
11
python test.py -v
# verbosity turned on: 1

python test.py -vvvv
# verbosity turned on: 4

python test.py -vvvv --verbosity
# verbosity turned on: 5

python test.py -vvvv --verbosity --verbosity
# verbosity turned on: 6

参数合法范围

例如

test.py
1
2
3
4
5
6
7
8
9
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-v", "--value", type=int, choices=[0, 1, 2],
help="value")
args = parser.parse_args()

if args.value:
print("value: {}".format(args.value))