argparse 是 Python 标准库中用于解析命令行参数的模块,它能将你在终端输入的文字,自动转换成 Python 代码可以使用的变量。

相比于手动处理 sys.argvargparse 的优势非常明显:它会自动生成帮助信息 (-h),进行类型转换与验证,并在用户输入错误时给出友好的错误提示

🏗️ 核心概念与基本用法

使用 argparse 主要遵循一个“三步走”的流程:

  1. 创建解析器:实例化 argparse.ArgumentParser 对象。

  2. 添加参数:使用 add_argument() 方法定义你希望程序接受的参数。

  3. 解析参数:调用 parse_args() 解析命令行输入,获取包含所有参数值的对象。

import argparse

# 1. 创建解析器
parser = argparse.ArgumentParser(description="一个简单的示例程序")

# 2. 添加参数
parser.add_argument("filename", help="要处理的文件名")          # 位置参数
parser.add_argument("-v", "--verbose", action="store_true", help="显示详细信息") # 可选参数

# 3. 解析参数
args = parser.parse_args()

# 使用参数
print(f"正在处理文件: {args.filename}")
if args.verbose:
    print("详细模式已开启")

📝 详解 add_argument()

add_argument() 是 argparse 的核心,它通过不同的参数来定制解析行为。

1. 参数类型:位置参数 vs 可选参数

这是理解 argparse 的基础。

类型特征是否必须示例 (add_argument)命令行调用
位置参数参数名不以 - 或 -- 开头parser.add_argument("filename")python script.py data.txt
可选参数参数名以 - (短选项) 或 -- (长选项) 开头parser.add_argument("-v", "--verbose")python script.py -v 或 python script.py --verbose
2. 核心参数详解

add_argument() 支持多种参数来精确控制解析行为。

  • action: 定义当参数被触发时的行为。

    • 'store_true' / 'store_false': 常用于开关/标志。如果命令行中出现了该参数,则将其值设为 True 或 False

    • 'store': 默认行为,存储一个值。

    • 'append': 允许同一个选项出现多次,并将所有值存储在一个列表中。

    • 'count': 统计选项出现的次数。

  • type: 指定参数的数据类型,argparse 会自动进行类型转换和校验。默认为字符串(str)。

parser.add_argument("--age", type=int, help="你的年龄")

如果用户输入 --age abcargparse 会直接报错。

  • default: 为参数设置默认值。如果命令行未提供,则使用此值。

parser.add_argument("--city", default="Shanghai", help="城市名")
  • required: 将某个可选参数变为必须提供的。通常不推荐过度使用,因为它违背了“可选”的初衷。
parser.add_argument("--mode", required=True, help="运行模式")
  • help: 为该参数添加帮助信息,当用户使用 -h 或 --help 时显示。
parser.add_argument("--output", help="输出文件路径")

nargs: 指定一个参数可以接受值的数量。

  • N (一个整数): 要求恰好 N 个值。

  • '?': 接受 0 个或 1 个值。

  • '*': 接受 0 个或多个值,结果是一个列表。

  • '+': 接受 1 个或多个值,结果是一个列表。

# 可以接受一个或多个文件
parser.add_argument('files', nargs='+', help='一个或多个文件')
  • choices: 将参数的值限制在一个预定义的集合内。
parser.add_argument("--color", choices=['red', 'green', 'blue'], help="选择颜色")
  • metavar: 在帮助信息中,为参数值提供一个不同的显示名称。
# 帮助信息会显示为: --output OUTPUT_FILE
parser.add_argument("--output", metavar="OUTPUT_FILE", help="输出文件路径")
  • dest: 自定义解析后,在 args 对象中访问该参数值的属性名。默认情况下,对于可选参数 --my-option,属性名是 my_option

🚀 进阶用法与实用技巧

掌握了基础后,这些进阶技巧能让你的 CLI 程序更加强大和易用。

1. 参数分组 (add_argument_group)

当参数很多时,将它们逻辑分组可以显著提高帮助信息的可读性。

import argparse

parser = argparse.ArgumentParser(description="模型训练脚本")
# 创建两个参数组
io_group = parser.add_argument_group('输入/输出参数')
train_group = parser.add_argument_group('训练参数')

io_group.add_argument("--input", required=True, help="输入数据路径")
io_group.add_argument("--output", default="./output", help="输出目录")

train_group.add_argument("--epochs", type=int, default=10, help="训练轮数")
train_group.add_argument("--batch-size", type=int, default=32, help="批次大小")

args = parser.parse_args()
2. 子命令 (subparsers)

对于复杂的工具(如 git,它有 git clonegit commit 等子命令),argparse 提供了子命令的支持。

import argparse

parser = argparse.ArgumentParser(description="一个支持子命令的工具")
subparsers = parser.add_subparsers(dest='command', required=True, help='子命令')

# 创建 'greet' 子命令
parser_greet = subparsers.add_parser('greet', help='打招呼')
parser_greet.add_argument('name', help='名字')

# 创建 'goodbye' 子命令
parser_goodbye = subparsers.add_parser('goodbye', help='说再见')
parser_goodbye.add_argument('--formal', action='store_true', help='正式地说')

args = parser.parse_args()

if args.command == 'greet':
    print(f"Hello, {args.name}!")
elif args.command == 'goodbye':
    if args.formal:
        print("Farewell.")
    else:
        print("Bye!")

命令行调用方式

python script.py greet Alice
python script.py goodbye --formal
3. 互斥选项 (add_mutually_exclusive_group)

确保用户只能从一组选项中选择一个-。

group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--sum', action='store_true', help='求和')
group.add_argument('--max', action='store_true', help='求最大值')
# 用户必须且只能选择 --sum 或 --max 中的一个
4. 从文件读取参数 (fromfile_prefix_chars)

在某些时候,如在处理一个特别长的参数列表时,把参数列表保存在一个文件中而不是在命令行中打印出来会更有意义。如果提供 fromfile_prefix_chars= 参数给 ArgumentParser 构造器,则任何以指定字符打头的参数都将被当作文件来处理,并将被它们包含的参数所替代。举例来说:

with open('args.txt', 'w', encoding=sys.getfilesystemencoding()) as fp:
    fp.write('-f\nbar')

parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument('-f')
parser.parse_args(['-f', 'foo', '@args.txt'])

从文件读取的参数在默认情况下必须一个一行 (但是可参见 convert_arg_line_to_args()) 并且它们被视为与命令行上的原始文件引用参数位于同一位置。所以在以上例子中,['-f', 'foo', '@args.txt'] 的表达式和 ['-f', 'foo', '-f', 'bar'] 的表达式相同。

fromfile_prefix_chars= 参数默认为 None,意味着参数不会被当作文件对待。

更多细节可参考 官方文档https://docs.python.org/3/library/argparse.html#fromfile-prefix-chars

5. 自定义类型转换

除了 intfloat 等内置类型,你可以传入任何可调用对象(如函数)来进行自定义转换。

def positive_int(value):
    ivalue = int(value)
    if ivalue <= 0:
        raise argparse.ArgumentTypeError(f"{value} 不是正整数")
    return ivalue

parser.add_argument("--count", type=positive_int, help="一个正整数")

🔧 最佳实践与常见陷阱

  • 总是提供 help 参数:为每个参数添加清晰的帮助信息,这能极大提升工具的易用性-1

  • 善用 description 和 epilog:为你的程序提供更丰富的上下文说明-10

  • 定义 prog 名称:在 ArgumentParser 中设置 prog 可以覆盖程序名,使帮助信息更专业-1-10

  • 捕获解析异常:如果你不希望 argparse 在出错时直接退出程序,可以捕获 SystemExit 异常-4

  • 避免在可选参数上滥用 required=True:这通常意味着你的接口设计可能需要重新思考。

  • 注意 nargs='*' 与可选参数的交互:当位置参数使用 nargs='*' 时,它后面的可选参数可能无法被正确解析。通常的解决方案是强制所有可选参数出现在位置参数之前。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐