【问题标题】:Is it possible to inherit required options in argparse subparsers?是否可以在 argparse 子解析器中继承所需的选项?
【发布时间】:2019-07-11 07:59:28
【问题描述】:

我正在尝试编写一个命令行应用程序,它具有多种运行模式(类似于git 具有clonepull 等)。我的每个子命令都有自己的选项,但我也希望它们共享一组必需的选项,所以我尝试使用父解析器来实现它。但是,似乎继承一个必需的选项会导致子解析器继续要求它。这是一个重新创建行为的示例:

import argparse

parent_parser = argparse.ArgumentParser(description="The parent parser")

parent_parser.add_argument("-p", type=int, required=True,
                           help="set the parent required parameter")

subparsers = parent_parser.add_subparsers(title="actions", required=True, dest='command')
parser_command1 = subparsers.add_parser("command1", parents=[parent_parser],
                                      add_help=False,
                                      description="The command1 parser",
                                      help="Do command1")
parser_command1.add_argument("--option1", help="Run with option1")

parser_command2 = subparsers.add_parser("command2", parents=[parent_parser],
                                      add_help=False,
                                      description="The command2 parser",
                                      help="Do command2")

args = parent_parser.parse_args()

所以现在如果我运行 python test.py 我会得到:

usage: test.py [-h] -p P {command1,command2} ...
test.py: error: the following arguments are required: -p, command

好的,到目前为止一切顺利。然后,如果我尝试使用 python test.py -p 3 仅指定 -p 选项,我会得到:

usage: test.py [-h] -p P {command1,command2} ...
test.py: error: the following arguments are required: command

但是如果我运行python test.py -p 3 command1 我明白了:

usage: test.py command1 [-h] -p P [--option1 OPTION1] {command1,command2} ...
test.py command1: error: the following arguments are required: -p, command

如果我添加另一个-p 3,它仍然要求再次指定command,然后如果我再次添加它,它会要求另一个-p 3等等。

如果我不要求 -p 选项,问题就解决了,但是有没有办法在多个子解析器之间共享所需的选项,而不只是在每个子解析器中复制粘贴它们?还是我完全走错了路?

【问题讨论】:

  • 你告诉parent_parserparser_command1 都需要一个'-p' 参数。所以你必须test.py -p 1 command1 -p 2等。每个级别都满足自己的要求。你仍然可以使用parent_parser 来填充子解析器,但是定义一个单独的main_parser 不需要'-p'。

标签: python-3.x argparse


【解决方案1】:

分离主解析器和父解析器功能:

import argparse

parent_parser = argparse.ArgumentParser(description="The parent parser", add_help=False)

parent_parser.add_argument("-p", type=int, required=True,
                           help="set the parent required parameter")


main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(title="actions", required=True, dest='command')
parser_command1 = subparsers.add_parser("command1", parents=[parent_parser],
                                      description="The command1 parser",
                                      help="Do command1")
parser_command1.add_argument("--option1", help="Run with option1")

parser_command2 = subparsers.add_parser("command2", parents=[parent_parser],
                                      description="The command2 parser",
                                      help="Do command2")

args = main_parser.parse_args()

主解析器和子解析器都写入同一个args 命名空间。如果两者都定义了 'p' 参数,则子解析器的值(或默认值)将覆盖主解析器设置的任何值。因此可以在两者中使用相同的“dest”,但这通常不是一个好主意。每个解析器都必须满足自己的“必需”规范。没有“分享”。

parents 机制将参数从父级复制到子级。所以它节省了打字或复制粘贴,但几乎没有。当父级在别处定义并导入时,它最有用。实际上它是通过引用复制的,这有时会引发问题。一般来说,同时运行父母和孩子并不是一个好主意。使用“虚拟”父级。

【讨论】:

    猜你喜欢
    • 2014-06-14
    • 2013-12-21
    • 2012-01-21
    • 1970-01-01
    • 2020-09-26
    • 2020-09-03
    • 1970-01-01
    • 2019-05-04
    相关资源
    最近更新 更多