Python argparse - 向多个子解析器添加参数

2025-04-01 09:56:00
admin
原创
3
摘要:问题描述:我的脚本定义了一个主解析器和多个子解析器。我想将-p参数应用于一些子解析器。到目前为止,代码如下所示:parser = argparse.ArgumentParser(prog="myProg") subparsers = parser.add_subparsers(title=...

问题描述:

我的脚本定义了一个主解析器和多个子解析器。我想将-p参数应用于一些子解析器。到目前为止,代码如下所示:

parser = argparse.ArgumentParser(prog="myProg")
subparsers = parser.add_subparsers(title="actions")

parser.add_argument("-v", "--verbose",
                    action="store_true",
                    dest="VERBOSE",
                    help="run in verbose mode")

parser_create = subparsers.add_parser ("create", 
                                        help = "create the orbix environment")
parser_create.add_argument ("-p", 
                            type = int, 
                            required = True, 
                            help = "set db parameter")

# Update
parser_update = subparsers.add_parser ("update", 
                                        help = "update the orbix environment")
parser_update.add_argument ("-p", 
                            type = int, 
                            required = True, 
                            help = "set db parameter")

如您所见,add_arument ("-p")重复了两次。实际上,我还有更多子解析器。有没有办法循环遍历现有的子解析器以避免重复?

为了记录,我使用的是 Python 2.7


解决方案 1:

由@hpaulj 更新

由于自 2011 年以来处理子解析器的方式发生了变化,将主解析器用作 不是一个好主意parent。更一般地说,不要尝试dest在主解析器和子解析器中定义相同的参数(相同的 )。子解析器值将覆盖主解析器设置的任何内容(即使子解析器也default会这样做)。创建单独的解析器以用作parents。并且如文档中所示,父级应该使用add_help=False


原始答案

这可以通过定义包含公共选项的父解析器来实现:

import argparse

parent_parser = argparse.ArgumentParser(description="The parent parser")
parent_parser.add_argument("-p", type=int, required=True,
                           help="set db parameter")
subparsers = parent_parser.add_subparsers(title="actions")
parser_create = subparsers.add_parser("create", parents=[parent_parser],
                                      add_help=False,
                                      description="The create parser",
                                      help="create the orbix environment")
parser_create.add_argument("--name", help="name of the environment")
parser_update = subparsers.add_parser("update", parents=[parent_parser],
                                      add_help=False,
                                      description="The update parser",
                                      help="update the orbix environment")

这将产生以下格式的帮助信息:

parent_parser.print_help()

输出:

usage: main.py [-h] -p P {create,update} ...
The parent parser
optional arguments:
  -h, --help       show this help message and exit
  -p P             set db parameter
actions:
  {create,update}
    create         create the orbix environment
    update         update the orbix environment
parser_create.print_help()

输出:

usage: main.py create [-h] -p P [--name NAME] {create,update} ...
The create parser
optional arguments:
  -h, --help       show this help message and exit
  -p P             set db parameter
  --name NAME      name of the environment
actions:
  {create,update}
    create         create the orbix environment
    update         update the orbix environment

但是,如果您运行程序,则如果您未指定操作(即createupdate),则不会遇到错误。如果您需要此行为,请按如下方式修改代码。

<...>
subparsers = parent_parser.add_subparsers(title="actions")
subparsers.required = True
subparsers.dest = 'command'
<...>

这个修复是在这个 SO 问题中提出的,它指的是跟踪拉取请求的问题。

解决方案 2:

接受的答案是正确的;正确的方法是使用父解析器。但是,示例代码在我看来并没有真正解决问题。让我补充几点意见,提供一个更合适的例子。

与接受的答案的主要区别在于明确可能有一些根级参数(如--verbose)以及仅对某些子解析器共享的参数(-p仅适用于create和子update解析器,但不适用于其他子解析器)

# Same main parser as usual
parser = argparse.ArgumentParser()

# Usual arguments which are applicable for the whole script / top-level args
parser.add_argument('--verbose', help='Common top-level parameter',
                    action='store_true', required=False)

# Same subparsers as usual
subparsers = parser.add_subparsers(help='Desired action to perform', dest='action')

# Usual subparsers not using common options
parser_other = subparsers.add_parser("extra-action", help='Do something without db')

# Create parent subparser. Note `add_help=False` and creation via `argparse.`
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('-p', help='add db parameter', required=True)

# Subparsers based on parent

parser_create = subparsers.add_parser("create", parents=[parent_parser],
                                      help='Create something')
# Add some arguments exclusively for parser_create

parser_update = subparsers.add_parser("update", parents=[parent_parser],
                                      help='Update something')
# Add some arguments exclusively for parser_update 

这是顶级帮助消息(请注意-p,这里未显示参数,这正是您所期望的 - 因为它特定于某些子解析器):

>>> parser.print_help()
usage: [-h] [--verbose] {extra-action,create,update} ...

positional arguments:
  {extra-action,create,update}
                        Desired action to perform
    extra-action        Do something without db
    create              Create something
    update              Update something

optional arguments:
  -h, --help            show this help message and exit
  --verbose             Common top-level parameter

以及该操作的帮助信息create

>>> parser_create.print_help()
usage:  create [-h] -p P

optional arguments:
  -h, --help  show this help message and exit
  -p P        add db parameter

解决方案 3:

您还可以循环遍历子解析器并向所有子解析器添加相同的选项。

parser = argparse.ArgumentParser(prog="myProg")
subparsers = parser.add_subparsers(title="actions")
parser.add_argument("-v", "--verbose",
                    action="store_true",
                    dest="VERBOSE",
                    help="run in verbose mode")

parser_create = subparsers.add_parser ("create", 
                                        help = "create the orbix environment")
parser_update = subparsers.add_parser ("update", 
                                        help = "update the orbix environment")

for subparser in [parser_create, parser_update]:
    subparser.add_argument ("-p", 
                            type = int, 
                            required = True, 
                            help = "set db parameter")

解决方案 4:

您可以按照以下方式循环遍历子解析器。

for name, subp in subparsers.choices.items():
    print(subp)
    subp.add_argument(dest='g', help='Input for g variable', default=7, type=int)

请注意,通过使用subparsers.choices它可以避免对所有子解析器进行硬编码。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2059  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1456  
  PLM(产品生命周期管理)软件在汽车行业正发挥着日益重要的作用,它贯穿于汽车从概念设计到退役处理的整个生命周期,为汽车企业提升效率、降低成本、提高产品质量提供了强大的支持。通过实际应用案例的解析,能更直观地了解PLM软件在汽车行业的价值与影响。PLM软件助力汽车设计创新在汽车设计阶段,PLM软件为设计师提供了一个协同的...
plm项目管理系统   0  
  企业数字化转型已成为当今众多企业寻求突破与发展的关键战略。在这一进程中,产品生命周期管理(PLM)系统发挥着至关重要的作用。PLM系统涵盖了从产品概念设计到产品退役的全生命周期管理,通过整合数据、流程和人员,为企业数字化转型提供了强大的支持。它不仅能提升企业内部的协同效率,还能优化产品创新流程,增强企业对市场变化的响应...
plm软件   2  
  产品生命周期管理(PLM)系统旨在整合产品从概念设计到退役的全生命周期数据与流程,助力企业提升创新能力、缩短产品上市时间、降低成本。然而,在PLM系统实施过程中,企业往往会遭遇诸多挑战。这些挑战若得不到妥善解决,将严重影响系统的实施效果与企业的业务发展。接下来,我们深入探讨PLM系统实施过程中常见的三大挑战。业务流程与...
plm系统主要干什么的   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用