如何向 argpare 解析器添加更多子解析器?
How can I add more subparsers to an argpare parser?
如果我的代码调用了一个 returns 和 ArgumentParser
已经定义了一些子解析器的函数,我该如何添加更多子解析器?
我想做这件事:
parser_with_subparsers = build_parser()
additional_subparsers = parser_with_subparsers.add_subparsers()
extra_subparser = additional_subparsers.add_parser("extra", help="extra help"))
但是当我在解释器中尝试这样做时:
>>> parser_with_subparsers = build_parser()
>>> additional_subparsers = parser_with_subparsers.add_subparsers()
usage: [-h] {original_subparser} ...
: error: cannot have multiple subparser arguments
请注意,我无权访问 build_parser()
函数的内部结构。
我能想到的唯一解决方案是使用 parents
,但这具有以一种奇怪的方式对子解析器进行分组的副作用:
>>> child_parser = argparse.ArgumentParser(parents=[build_parser()])
>>> additional_subparsers = child_parser.add_subparsers()
>>> extra_subparser = additional_subparsers.add_parser("extra", help="extra help")
>>> extra_subparser2 = additional_subparsers.add_parser("extra2", help="extra2 help")
>>> child_parser.print_help()
usage: [-h] {original_subparser} ... {extra,extra2} ...
positional arguments:
{original_subparser}
original_subparser original_subparser help
{extra,extra2}
extra extra help
extra2 extra2 help
optional arguments:
-h, --help show this help message and exit
我想这样做的原因是我想在我继承的 Argument Parser
中添加额外的 'commands'。
您希望添加的子解析器有什么样的行为?
sp = parser.add_subparsers(...)
add_subparsers
创建 _SubParsersAction
class 的位置参数,并在 parser._subparsers
属性中记录它。如果已经设置了该属性,则会引发该错误。 sp
是 Action
对象。
从逻辑上讲,有多个 'subparsers' 操作是没有意义的。当主解析器遇到子解析器命令时,它将解析委托给该子解析器。除了一些清理错误检查之外,主解析器不会恢复解析。所以它无法处理第二个子解析器命令。
(add_subparsers
创建的术语和 add_parser
所做的术语可能令人困惑。一个是位置 argument/Action,另一个是解析器([=24= 的实例]).
应该可以将新的解析器添加到现有的 subparsers
操作中(我必须尝试找到一种干净的方法来执行此操作)。也可以添加嵌套子解析器,即为子解析器定义 add_subparsers
。
parents
方法绕过了这个multiple subparser arguments
测试,可能是因为它没有在第一次设置 parser._subparsers
属性(从父级复制操作时)。因此实际上创建了两个 subparser arguments
。这就是 help
显示的内容。但我的猜测是解析将没有意义。它仍然会期待 'original_subparser' 而不是寻找 'extra' 或 'extra2'.
parents
机制不健全。它有直接的用途,但很容易损坏。
In [2]: parser = argparse.ArgumentParser(prog='main')
In [3]: a1 = parser.add_argument('--foo')
In [4]: parser._subparsers # initial value None
In [5]: sp = parser.add_subparsers(dest='cmd')
In [6]: parser._subparsers # new non-None value
Out[6]: <argparse._ArgumentGroup at 0xaf780f0c>
sp
对象,一个Action子class:
In [8]: sp
Out[8]: _SubParsersAction(option_strings=[], dest='cmd', nargs='A...', const=None, default=None, type=None, choices=OrderedDict(), help=None, metavar=None)
In [9]: sp1 = sp.add_parser('cmd1')
sp
是一个动作(位置参数); sp1
是一个解析器。
In [10]: parser.print_help()
usage: main [-h] [--foo FOO] {cmd1} ...
positional arguments:
{cmd1}
optional arguments:
-h, --help show this help message and exit
--foo FOO
_actions
属性是一个动作列表。注意 help
和 foo
In [12]: parser._subparsers._actions
Out[12]:
[_HelpAction(option_strings=['-h', '--help'], dest='help',...),
_StoreAction(option_strings=['--foo'], dest='foo',....),
_SubParsersAction(option_strings=[], dest='cmd', ...]
因此此列表中的最后一项是 sp
对象
In [13]: parser._subparsers._actions[-1]
Out[13]: _SubParsersAction(option_strings=[], dest='cmd', nargs='A...', const=None, default=None, type=None, choices=OrderedDict([('cmd1', ArgumentParser(prog='main cmd1', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True))]), help=None, metavar=None)
所以我们可以添加一个新的子解析器
In [14]: parser._subparsers._actions[-1].add_parser('extra')
...
In [15]: parser.print_help()
usage: main [-h] [--foo FOO] {cmd1,extra} ...
positional arguments:
{cmd1,extra}
optional arguments:
-h, --help show this help message and exit
--foo FOO
因此,如果您只想将 extra
和 extra2
添加到 original_subparser
,这应该可行。
所以只要我们不再尝试 parser.add_argument(...)
抓取最后一个 _actions
项目就应该可以。如果不是最后一次,我们将不得不进行更复杂的搜索。
从我的代表变化来看,有人发现了这个对 _subparsers
属性的早期探索:
如果我的代码调用了一个 returns 和 ArgumentParser
已经定义了一些子解析器的函数,我该如何添加更多子解析器?
我想做这件事:
parser_with_subparsers = build_parser()
additional_subparsers = parser_with_subparsers.add_subparsers()
extra_subparser = additional_subparsers.add_parser("extra", help="extra help"))
但是当我在解释器中尝试这样做时:
>>> parser_with_subparsers = build_parser()
>>> additional_subparsers = parser_with_subparsers.add_subparsers()
usage: [-h] {original_subparser} ...
: error: cannot have multiple subparser arguments
请注意,我无权访问 build_parser()
函数的内部结构。
我能想到的唯一解决方案是使用 parents
,但这具有以一种奇怪的方式对子解析器进行分组的副作用:
>>> child_parser = argparse.ArgumentParser(parents=[build_parser()])
>>> additional_subparsers = child_parser.add_subparsers()
>>> extra_subparser = additional_subparsers.add_parser("extra", help="extra help")
>>> extra_subparser2 = additional_subparsers.add_parser("extra2", help="extra2 help")
>>> child_parser.print_help()
usage: [-h] {original_subparser} ... {extra,extra2} ...
positional arguments:
{original_subparser}
original_subparser original_subparser help
{extra,extra2}
extra extra help
extra2 extra2 help
optional arguments:
-h, --help show this help message and exit
我想这样做的原因是我想在我继承的 Argument Parser
中添加额外的 'commands'。
您希望添加的子解析器有什么样的行为?
sp = parser.add_subparsers(...)
add_subparsers
创建 _SubParsersAction
class 的位置参数,并在 parser._subparsers
属性中记录它。如果已经设置了该属性,则会引发该错误。 sp
是 Action
对象。
从逻辑上讲,有多个 'subparsers' 操作是没有意义的。当主解析器遇到子解析器命令时,它将解析委托给该子解析器。除了一些清理错误检查之外,主解析器不会恢复解析。所以它无法处理第二个子解析器命令。
(add_subparsers
创建的术语和 add_parser
所做的术语可能令人困惑。一个是位置 argument/Action,另一个是解析器([=24= 的实例]).
应该可以将新的解析器添加到现有的 subparsers
操作中(我必须尝试找到一种干净的方法来执行此操作)。也可以添加嵌套子解析器,即为子解析器定义 add_subparsers
。
parents
方法绕过了这个multiple subparser arguments
测试,可能是因为它没有在第一次设置 parser._subparsers
属性(从父级复制操作时)。因此实际上创建了两个 subparser arguments
。这就是 help
显示的内容。但我的猜测是解析将没有意义。它仍然会期待 'original_subparser' 而不是寻找 'extra' 或 'extra2'.
parents
机制不健全。它有直接的用途,但很容易损坏。
In [2]: parser = argparse.ArgumentParser(prog='main')
In [3]: a1 = parser.add_argument('--foo')
In [4]: parser._subparsers # initial value None
In [5]: sp = parser.add_subparsers(dest='cmd')
In [6]: parser._subparsers # new non-None value
Out[6]: <argparse._ArgumentGroup at 0xaf780f0c>
sp
对象,一个Action子class:
In [8]: sp
Out[8]: _SubParsersAction(option_strings=[], dest='cmd', nargs='A...', const=None, default=None, type=None, choices=OrderedDict(), help=None, metavar=None)
In [9]: sp1 = sp.add_parser('cmd1')
sp
是一个动作(位置参数); sp1
是一个解析器。
In [10]: parser.print_help()
usage: main [-h] [--foo FOO] {cmd1} ...
positional arguments:
{cmd1}
optional arguments:
-h, --help show this help message and exit
--foo FOO
_actions
属性是一个动作列表。注意 help
和 foo
In [12]: parser._subparsers._actions
Out[12]:
[_HelpAction(option_strings=['-h', '--help'], dest='help',...),
_StoreAction(option_strings=['--foo'], dest='foo',....),
_SubParsersAction(option_strings=[], dest='cmd', ...]
因此此列表中的最后一项是 sp
对象
In [13]: parser._subparsers._actions[-1]
Out[13]: _SubParsersAction(option_strings=[], dest='cmd', nargs='A...', const=None, default=None, type=None, choices=OrderedDict([('cmd1', ArgumentParser(prog='main cmd1', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True))]), help=None, metavar=None)
所以我们可以添加一个新的子解析器
In [14]: parser._subparsers._actions[-1].add_parser('extra')
...
In [15]: parser.print_help()
usage: main [-h] [--foo FOO] {cmd1,extra} ...
positional arguments:
{cmd1,extra}
optional arguments:
-h, --help show this help message and exit
--foo FOO
因此,如果您只想将 extra
和 extra2
添加到 original_subparser
,这应该可行。
所以只要我们不再尝试 parser.add_argument(...)
抓取最后一个 _actions
项目就应该可以。如果不是最后一次,我们将不得不进行更复杂的搜索。
从我的代表变化来看,有人发现了这个对 _subparsers
属性的早期探索: