1、简介
argparse是python的标准库模块之一,用于在命令行接口中处理参数和选项。使得python脚本可以接收用户输入的参数和选项,用于控制程序的行为。
与sys.argv的区别
1)sys.argv获取的命令行参数,参数需要手动解析,开发者需要自己编写代码来处理参数的解析、验证和错误处理。
2)argparse相比sys.argsv,argparse 更加强大,适合用于复杂的命令行参数解析,能大大减少手动解析和错误处理的负担,并提供自动化的帮助和验证功能。
2、基本用法
以下是 argparse 的基本使用步骤:
- 导入模块:导入 argparse。
- 创建解析器:使用 argparse.argumentparser() 创建一个解析器对象。
- 添加参数:通过 add_argument() 方法向解析器添加参数。
- 解析参数:使用 parse_args() 方法解析传入的命令行参数。
- 使用参数:通过访问解析结果对象的属性来使用参数。
示例:
import argparse
def get_args():
# 创建 argumentparser 对象
parser = argparse.argumentparser(description="示例 python 脚本使用 argparse 解析命令行参数")
# 添加参数
parser.add_argument('name', type=str, help='你的名字') # 必须的参数
parser.add_argument('-a', '--age', type=int, default=20, help='你的年龄(可选,默认20)') # 可选参数
parser.add_argument('-v', '--verbose', action='store_true', help='详细模式') # 布尔开关
# 解析命令行参数
args = parser.parse_args()
# 使用解析的参数
print(f"你好, {args.name}!")
print(f"你的年龄是: {args.age}")
if args.verbose:
print("详细模式已开启。")
if __name__ == '__main__':
get_args()
假设上面的代码保存在一个文件 example.py 中,你可以在命令行中运行以下命令:
python example.py zhangsan -a 30 --verbose
输出结果:
你好, zhangsan! 你的年龄是: 21 详细模式已开启。
3、详细讲解每个部分
3.1 创建argumentparser 对象
argparse 模块对命令行接口的支持是基于 argparse.argumentparser 的实例建立的。
parser = argparse.argumentparser( description="示例 python 脚本使用 argparse 解析命令行参数", formatter_class=argparse.argumentdefaultshelpformatter )
description:这个参数简要描述这个程序做什么以及怎么做。当用户使用 -h 或 --help 时显示。formatter_class:这个参数指定特定的格式化类来自定义帮助信息的格式。
目前,有四种这样的类:
class argparse.rawdescriptionhelpformatter class argparse.rawtexthelpformatter class argparse.argumentdefaultshelpformatter¶ class argparse.metavartypehelpformatter
一般使用:argumentdefaultshelpformatter 自动添加默认的值的信息到每一个帮助信息的参数中。
3.2 添加参数
解析器对象通过调用 add_argument() 方法添加程序参数信息。这些调用指定 argumentparser 对象如何获取命令行字符串并将其转换为对象。
1)语法:
argumentparser.add_argument(name or flags…[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest]) 定义单个的命令行参数应当如何解析。
2)位置参数
parser.add_argument('name', type=str, help='你的名字')
位置参数:如果指定了位置参数,在命令行参数中是必填项,直接写在脚本之后。
3)可选参数
parser.add_argument('-a', '--age', type=int, default=20, help='你的年龄(可选,默认20)')
可选参数:在命令行中参数名以 - 或 – 开头;所谓可选是指在命令行可指定参数或者不指定。如果不指定则使用默认值,由default 参数提供默认值。
4)参数说明
name or flags - 用于定义参数的名称或标志;位置参数(必填),可选参数(带前缀 - 或 --),示例:
parser.add_argument('filename') # 位置参数
parser.add_argument('-v', '--verbose') # 可选参数
type - 指定命令行参数应当被转换成的类型或转换函数,常见类型有 int、float、str,示例:
parser.add_argument('--count', type=int) # 将输入值转换为整数
default - 指定参数的默认值,如果不指定参数则使用默认值,示例:
parser.add_argument('--age', type=int, default=18) # 默认值为 18
help - 提供参数的帮助说明,在 --help 或 -h 选项中显示,示例:
parser.add_argument('--verbose', help='启用详细模式') # 提供参数的帮助信息
required - 指定参数是否是必需的,通常用于可选参数(required=true),示例:
parser.add_argument('--output', required=true) # 必须提供 --output 参数
action - 指定了这个命令行参数应当如何处理,将命令行参数与动作相关联,大多数动作只是简单的向 parse_args() 返回的对象上添加属性。常见的动作有:
- ‘store’(默认):存储参数的值。示例
parser = argparse.argumentparser()
parser.add_argument('--foo')
parser.parse_args('--foo 1'.split())
# 结果:namespace(foo='1')
将参数和值存储到namespace对象中
- ‘store_const’:存储 由 const 关键字参数指定的值(通常与 nargs=‘?’ 一起使用)。常用于指定某类flag的可选参数。示例:
parser = argparse.argumentparser()
parser.add_argument('--foo', action='store_const', const=42)
parser.parse_args(['--foo'])
namespace(foo=42)
- ‘store_true’ 和 ‘store_false’ - 这是 ‘store_const’ 动作分别用作存储 true 和 false 值的特殊用例。另外,它们的默认值分别为 true和false。常用于布尔开关。
- ‘append’ - 存储一个列表,并将每个参数值添加到该列表。它适用于允许可多次指定的选项。 如果默认值非空,则默认的元素将出现在该选项的已解析值中,并将所有来自命令行的值添加在默认值之后。
parser = argparse.argumentparser()
parser.add_argument('--foo', action='append')
parser.parse_args('--foo 1 --foo 2'.split())
namespace(foo=['1', '2'])
nargs - 指定参数的个数,支持的符号:
- n(一个整数)。接收参数的数量,命令行中的 n 个参数会被聚集到一个列表中。 例如:
parser = argparse.argumentparser()
parser.add_argument('--range', nargs=2)
parser.add_argument('bar', nargs=1)
parser.parse_args('c --range 1 10'.split())
namespace(bar=['c'], foo=['1', '10'])
注意 nargs=1 会产生一个单元素列表。这和默认的元素本身是不同的。
- ‘?’:可选一个参数,没有时使用 const 值。
parser = argparse.argumentparser()
parser.add_argument('--foo', nargs='?', const='c', default='d')
parser.add_argument('bar', nargs='?', default='d')
parser.parse_args(['xx', '--foo', 'yy'])
namespace(bar='xx', foo='yy')
parser.parse_args(['xx', '--foo'])
namespace(bar='xx', foo='c')
parser.parse_args([])
namespace(bar='d', foo='d')
- ‘*’: 接收零或多个参数,作为列表传递给参数。
parser = argparse.argumentparser()
parser.add_argument('--foo', nargs='*')
parser.add_argument('--bar', nargs='*')
parser.add_argument('baz', nargs='*')
parser.parse_args('a b --foo x y --bar 1 2'.split())
namespace(bar=['1', '2'], baz=['a', 'b'], foo=['x', 'y'])
- ‘+’: 接收一个或多个参数,作为列表传递给参数。
parser = argparse.argumentparser(prog='prog')
parser.add_argument('foo', nargs='+')
parser.parse_args(['a', 'b'])
namespace(foo=['a', 'b'])
注意:如果没有给命令行参数传递至少一个值,会报错。
const - 当 action=‘store_const’ 或 nargs=‘?’ 时,指定参数的常量值。示例:
parser.add_argument('--level', nargs='?', const='medium', default='low') # 没有参数时使用 'medium'
chioces - 指定参数值的允许范围或可选列表。示例:
parser.add_argument('--color', choices=['red', 'green', 'blue']) # 只能选择 red, green, blue
dest: 指定存储参数值的属性名,该属性的名称由 add_argument() 的 dest 关键字参数确定,默认与参数名相同。
对于可选参数,dest 的值通常取自选项字符串。
argumentparser 会通过接受第一个长选项字符串并去掉开头的 -- 字符串来生成 dest 的值。
如果没有提供长选项字符串,则 dest 将通过接受第一个短选项字符串并去掉开头的 - 字符来获得。
参数名任何内部的 - 字符都将被转换为 _ 字符以确保字符串是有效的属性名称。
示例1:
parser = argparse.argumentparser()
parser.add_argument('-f', '--foo-bar', '--foo')
parser.add_argument('-x', '-y')
parser.parse_args('-f 1 -x 2'.split())
namespace(foo_bar='1', x='2')
示例2:
自定义属性名称
parser = argparse.argumentparser()
parser.add_argument('--foo', dest='bar')
parser.parse_args('--foo xxx'.split())
namespace(bar='xxx')
综合示例:
import argparse
# 创建 argumentparser 对象
parser = argparse.argumentparser(description="综合示例")
# 添加各种参数
parser.add_argument('filename', type=str, help='文件名') # 位置参数
parser.add_argument('-v', '--verbose', action='store_true', help='启用详细模式') # 布尔开关
parser.add_argument('--count', type=int, default=10, help='计数值(默认10)') # 带默认值的参数
parser.add_argument('--level', choices=['low', 'medium', 'high'], help='选择级别') # 限定选择值
parser.add_argument('--range', nargs=2, type=int, help='指定两个整数范围') # 接收两个整数
parser.add_argument('--option', nargs='?', const='special', help='可选参数,没有时为 special') # 带常量值的可选参数
# 解析命令行参数
args = parser.parse_args()
# 输出解析结果
print(f"文件名: {args.filename}")
print(f"详细模式: {args.verbose}")
print(f"计数值: {args.count}")
print(f"级别: {args.level}")
print(f"范围: {args.range}")
print(f"选项: {args.option}")
运行示例:
python script.py example.txt --verbose --count 5 --level high --range 10 20 --option
输出结果:
文件名: example.txt 详细模式: true 计数值: 5 级别: high 范围: [10, 20] 选项: special
3.3 解析参数
args = parser.parse_args(args=none, namespace=none)
解析传入的命令行参数并将其存储为 namespace对象的属性,返回值带有成员的namespace。
参数说明:
- args - 要解析的字符串列表。 默认值是从 sys.argv 获取。
- namespace - 用于获取属性的对象。 默认值是一个新的空 namespace 对象。
3.4 使用命令行参数
类似python对象使用内部属性一样,通过"."访问解析后的参数值。例如:
# 解析命令行参数
args = parser.parse_args()
# 使用解析的参数
print(f"你好, {args.name}!")
print(f"你的年龄是: {args.age}")
if args.verbose:
print("详细模式已开启。")
3.5 命名空间(argparse.namespace)
argparse.namespace 是 argparse 模块中的一个类,用于存储解析后的命令行参数。通过 argparse.argumentparser.parse_args() 方法解析参数后,会返回一个 namespace 对象,该对象的属性就是命令行参数的名称和值。
argparse.namespace 详解
- namespace 对象的主要作用是将解析后的命令行参数以属性的形式存储,从而方便在程序中访问这些参数。
- namespace 类本质上是一个简单的容器对象,类似于 python 的对象,可以动态地增加属性。
1、创建namespace对象
1)通过parser.parse_args()自动生成
2)手动创建namespace对象
from argparse import namespace # 手动创建 namespace 对象 args = namespace(name='bob', age=30) # 访问属性 print(args.name) # 输出: bob print(args.age) # 输出: 30
3)将字典转换为namespace
from argparse import namespace
# 从字典创建 namespace
data = {'name': 'charlie', 'age': 28}
args = namespace(**data)
print(args) # 输出: namespace(name='charlie', age=28)
2、namespace对象的常用操作
1)添加属性,动态添加属性
args = namespace() args.name = 'david' args.age = 40 print(args) # 输出: namespace(name='david', age=40)
2)修改属性
args.age = 35 print(args) # 输出: namespace(name='david', age=35)
3)删除属性
del args.name print(args) # 输出: namespace(age=35)
4)将 namespace 转换为字典:使用 vars() 函数将 namespace 对象转换为字典。
args_dict = vars(args)
print(args_dict) # 输出: {'name': 'david', 'age': 35}
3.6 paser对象中的action对象
1、action对象定义
action(option_strings, dest, nargs=none, const=none, default=none, type=none, choices=none, required=false, help=none, metavar=none)
2、使用示例和解析
使用示例:
inference_args_dict = {}
for action in parser._actions:
inference_args_dict[action.dest] = action.default
解析:
1)action 对象会被 argumentparser 用来表示解析从命令行中的一个参数所必须的信息,也就是一个action对象包含一个add_argument() 方法添加的参数信息,每个 action 对象代表一个命令行参数,并包含有关该参数的各种信息,如名称、类型、默认值、帮助文本等。
2)parser 是一个 argumentparser 对象,_actions 是其内部的一个列表,包含所有由 add_argument() 方法添加的参数信息(即 action 对象)。
3)for action in parser._actions:这个循环遍历 parser._actions 列表中的每个 action 对象;所以action 在每次迭代中代表一个参数对象。
3、action对象的属性
1)dest 是 action 对象的一个属性,表示参数值在 namespace 对象中的存储名称,即解析后的参数值将保存在这个名称的属性中。
例如,如果使用 parser.add_argument(‘–age’, dest=‘user_age’),则 dest 将是 ‘user_age’。
2)default 是 action 对象的另一个属性,表示该参数的默认值(如果未在命令行中提供参数时使用的值)。
如果没有为参数指定默认值,default 通常为 none,除非在 add_argument() 中显式指定。
4、实际使用中遇到的坑
4.1 使用argparse获取命令行bool型参数
1)错误使用:
def get_args():
parser = argparse.argumentparser(formatter_class=argparse.argumentdefaultshelpformatter)
parser.add_argument('--is_test', type=bool, default=false,
help='是否使用测试模式')
args = parser.parse_args()
return args
如果使用这种方式,会发现传递任何字符,args.is_test的结果都是true。因为python中非空字符串的bool值是true。
2)正确的使用方式:
def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return true
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return false
else:
raise argparse.argumenttypeerror('boolean value expected.')
def get_args():
parser = argparse.argumentparser(formatter_class=argparse.argumentdefaultshelpformatter)
parser.add_argument('--is_test', type=str2bool, default=false,
help='是否使用测试模式')
args = parser.parse_args()
return args
4.2 在程序中多次使用parser.parse_args()
导致意外行为,特别是在参数冲突或已经处理的参数被重新解析时。
如果你确实需要在程序中多次解析参数,一种有效的解决方案:
在整个程序中只调用一次parser.parse_args(), 后面使用parser对象来获取参数名和参数值。
def init_args():
parser = argparse.argumentparser()
# params for prediction engine
parser.add_argument("--gpu_mem", type=int, default=500)
parser.add_argument("--gpu_id", type=int, default=0)
return parser
def get_args():
parser = argparse.argumentparser(formatter_class=argparse.argumentdefaultshelpformatter)
parser.add_argument('--is_test', type=str2bool, default=false,
help='是否使用测试模式')
args = parser.parse_args()
return args
def main():
parser = init_args()
inference_args_dict = {}
for action in parser._actions:
inference_args_dict[action.dest] = action.default
args1 = argparse.namespace(**inference_args_dict)
args = get_args()
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论