82

我的脚本定义了一个主解析器和多个子解析器。我想将-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

4

4 回答 4

94

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

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 question中提出的,它指的是跟踪拉取请求的问题。

@hpaulj 更新

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

于 2011-09-21T11:19:20.217 回答
57

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

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

# 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
于 2019-06-14T09:51:29.650 回答
15

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

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")
于 2015-08-26T09:40:19.050 回答
8

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

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

于 2017-10-12T18:31:09.173 回答