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

问题描述 投票:0回答:4

我的脚本定义了一个主解析器和多个子解析器。我想将

-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

python argparse
4个回答
104
投票

更新@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

但是,如果您运行程序,如果不指定操作(即

create
update
),则不会遇到错误。如果您希望这种行为,请按如下方式修改您的代码。

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

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


72
投票

接受的答案是正确的;正确的方法是使用父解析器。然而,示例代码在我看来并没有真正解决问题。让我添加我的几分钱来提供一个更合适的例子。

与接受的答案的主要区别是明确可能有一些根级参数(如

--verbose
)以及仅适用于some子解析器的共享参数(
-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

18
投票

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

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")

10
投票

您可以通过以下方式循环子解析器。

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
,您可以避免需要对所有子解析器进行硬编码。

© www.soinside.com 2019 - 2024. All rights reserved.