整体说明
- 在 Python 里,
argparse.ArgumentParser()是标准库argparse模块的核心部分,其主要功能是解析命令行参数 - 大部分优秀的开源函数都会使用这个功能
代码示例
- ArgumentParser类使用示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85import argparse
def main():
# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(
description='这是一个命令行工具演示程序',
epilog='示例: python demo.py -n Alice -a 35 --verbose'
)
# 添加参数
# 位置参数 (未添加-为前缀的是位置参数,位置参数是必须给出的)
parser.add_argument('input_file', help='输入文件路径')
# 可选参数(添加-或--的是可选参数),同一行可以同时注册-或--,都可以作为输入参数
# # 但代码内部名字命名规则是--优先-,没有--时,代码内部-才会生效(比如下面的定义下,parser.output 和 parser.x 生效,但是 parser.o 会报错)
parser.add_argument('-o', '--output', default='output/result.txt', help='输出文件路径') # 调用时使用args.output调用参数
parser.add_argument('-x', help='x') # 调用时使用args.x调用参数
parser.add_argument('-n', '--name', default='Guest', help='用户名称') # 调用时使用args.x调用参数
parser.add_argument('--age', type=int, choices=range(30, 40), help='用户年龄(30-39)')
# action='store_true'表示这是布尔变量,若传入命令行存在该参数,则该 Python 参数值为 true,否则为 false;'store_false' 则功能相反
parser.add_argument('--verbose', action='store_true', help='显示详细输出')
parser.add_argument('--color', choices=['red', 'green', 'blue'], default='blue', help='颜色选择')
parser.add_argument('--scale', type=float, default=0, help='缩放比例')
# 互斥参数组,同时指定会出错
group = parser.add_mutually_exclusive_group()
group.add_argument('--fast', action='store_true', help='快速模式')
group.add_argument('--slow', action='store_true', help='慢速模式')
# 以上都是自动推导 dest,下面显示定义 dest(注意:dest 是真正在 args 中可以被使用的参数名称)
parser.add_argument("--use_flash_attn", action="store_true", dest="use_flash_attn", default=False)
## 而且可以考虑将同一个 dest 绑定多个输入参数,比如下面的句子使得可以同时通过 `--use_flash_attn` 和 `--no_use_flash_attn` 控制同一个参数:
parser.add_argument("--no_use_flash_attn", action="store_false", dest="use_flash_attn")
## dest 可以和原始的参数名完全无关(下面示例中 dest 与参数名不同,访问时要通过 args.enable_attention 而不是 args.use_attention)
parser.add_argument("--use_attention", action="store_true", dest="enable_attention", default=False)
# * 解析参数
args = parser.parse_args()
print("args对象完整属性:", args.__dict__)
print("--end--\n")
# * 使用参数
print(f"输入文件: {args.input_file}")
if args.output:
print(f"输出文件: {args.output}")
print(f"用户名: {args.name}")
if args.age:
print(f"年龄: {args.age}")
print(f"详细模式: {'是' if args.verbose else '否'}")
print(f"颜色: {args.color}")
print(f"缩放比例: {args.scale}")
if args.fast:
print("模式: 快速")
elif args.slow:
print("模式: 慢速")
else:
print("模式: 默认")
# 根据参数值给出提示
if args.use_flash_attn:
print("FlashAttention 已启用")
else:
print("FlashAttention 未启用")
if args.enable_attention:
print("Attention 已启用")
else:
print("Attention 未启用")
if __name__ == '__main__':
main()
# args对象完整属性: {'input_file': 'text.txt', 'output': 'output/result.txt', 'x': None, 'name': 'Guest', 'age': 33, 'verbose': False, 'color': 'blue', 'scale': 0, 'fast': False, 'slow': False, 'use_flash_attn': False, 'enable_an': False}
# --end--
#
# 输入文件: text.txt
# 输出文件: output/result.txt
# 用户名: Guest
# 年龄: 33
# 详细模式: 否
# 颜色: blue
# 缩放比例: 0
# 模式: 默认
# FlashAttention 未启用
# Attention 未启用
Python 内部变量参数命名规则
-和--同时存在时,优先--定义的变量- 注:传入时都可以使用,且没有优先级,只会用后面的覆盖前面的
--output-path等会自动被转换成parser.output_path变量访问- 注:传入时还是必须跟参数定义方式对齐
--output-path - 当然:
--output_path也是相同的参数名parser.output_path,若同时定义了--output_path和--output-path,则两者实际上是同一个参数,且互相之间可以被覆盖
- 注:传入时还是必须跟参数定义方式对齐
ArgumentParser 类其他使用注意事项
- 参数类型 :
- 默认情况下参数是字符串类型,可以使用
type指定其他类型 - 常用类型:
int,float,str(默认)
- 默认情况下参数是字符串类型,可以使用
- 参数种类 :
- 位置参数:没有前缀,必须提供
- 可选参数:以
-或--开头,可选提供 - 注:位置参数是必须的,可选参数可通过增加
required=True来设定为必须参数
- 常用参数选项 :
help:参数的帮助信息default:参数的默认值choices:限制参数的取值范围action:参数的动作,常见值:store:存储参数值(默认)store_true/store_false:存储布尔值append:允许多次使用参数并存储为列表
- 互斥参数 :
- 使用
add_mutually_exclusive_group()创建互斥组 - 组内的参数不能同时使用
- 使用
- 帮助信息 :
description:程序的简要描述epilog:帮助信息末尾的文本- 自动生成的帮助信息可以通过
-h或--help查看
- 错误处理 :
- 当用户输入无效参数时,
argparse会自动生成错误信息并退出,会抛出ArgumentError或SystemExit异常
- 当用户输入无效参数时,
- 子命令 :
- 对于复杂的命令行工具,可以使用
add_subparsers()实现子命令功能 - 类似
git的commit,push等子命令
- 对于复杂的命令行工具,可以使用
- 参数前缀 :
- 通常单字母参数用
-前缀,完整单词用--前缀 - 但这不是强制要求,只是约定俗成
- 通常单字母参数用
关于 dest 的特殊说明
dest决定了解析结果存储在args对象中的变量名 ,即通过args.xxx访问时的xxx1
2
3
4
5
6
7
8
9
10parser.add_argument(
"--use_flash_attn",
action="store_true",
dest="enable_flash", # dest 与参数名不同
default=False,
)
args = parser.parse_args()
args.enable_flash # 正确访问方式
args.use_flash_attn # AttributeError,dest 才是真正的变量名理解:
dest是args.xxx里的xxx,命令行参数名只是触发器,真正存数据的是dest
常见方式:自动推导规则(不写 dest)
- 自动推导
dest示例:1
2
3
4
5# 规则:去掉 -- 前缀,- 替换为 _
parser.add_argument("--use_flash_attn") # dest → "use_flash_attn"
parser.add_argument("--learning-rate") # dest → "learning_rate"
parser.add_argument("-v") # dest → "v"
parser.add_argument("--no_use_flash_attn") # dest → "no_use_flash_attn" ⚠️ 不是 use_flash_attn!
必须显式指定 dest 的场景
场景1:解决短选项名语义不清
1
2parser.add_argument("-v", dest="verbose")
# 否则只能用 args.v 访问,语义不明确场景2:多个参数映射到同一变量(最典型!)
1
2
3
4
5
6
7# 不指定 dest → 两个参数完全独立,互不影响
parser.add_argument("--use_flash_attn", action="store_true") # dest → use_flash_attn
parser.add_argument("--no_use_flash_attn", action="store_false") # dest → no_use_flash_attn
# 指定 dest → 两个参数绑定同一变量,形成开关联动
parser.add_argument("--use_flash_attn", action="store_true", dest="use_flash_attn", default=False)
parser.add_argument("--no_use_flash_attn", action="store_false", dest="use_flash_attn")- 执行结果:
1
2
3$ python test.py # Namespace(use_flash_attn=False)
$ python test.py --use_flash_attn # Namespace(use_flash_attn=True)
$ python test.py --no_use_flash_attn # Namespace(use_flash_attn=False)
- 执行结果:
场景3:参数名不是合法的变量名
1
2parser.add_argument("--2d-output", dest="output_2d")
# --2d-output 不能直接作为变量名(数字开头),用 dest 自定义
两个参数绑定到同一个目标参数上的实现
- 背景:有时候我们想要增加可读性,对于 布尔类型的变量可能会定义两个输入方式
- 比如同一个参数:添加
--use_flash_attn表示 True,添加--no_use_flash_attn时表示 False
- 比如同一个参数:添加
两个参数绑定到同一个目标参数上
示例:用
argparse实现布尔开关 ,两个参数共享同一个dest:1
2parser.add_argument("--use_flash_attn", action="store_true", dest="use_flash_attn", default=False)
parser.add_argument("--no_use_flash_attn", action="store_false", dest="use_flash_attn")- 注:之前我们一般不使用
dest参数,是因为dest会被自动推导,这里为了实现将同一个变量绑定到两个参数,需显示指定dest
- 注:之前我们一般不使用
不同传参下的运行结果:
命令行输入 args.use_flash_attnpython script.pyFalse(走 default)python script.py --use_flash_attnTruepython script.py --no_use_flash_attnFalsepython script.py --use_flash_attn --no_use_flash_attnFalse(后者覆盖前者)
补充:其他更推荐的写法(Python 3.9+)
使用
argparse.BooleanOptionalAction,更简洁:1
2
3
4
5
6parser.add_argument(
"--use_flash_attn",
action=argparse.BooleanOptionalAction, # 自动生成 --no_use_flash_attn
default=False,
help="Enable/Disable FlashAttention"
)两种写法效果完全等价,都支持
--use_flash_attn和--no-use_flash_attn两种形式