Python 如何向argpare解析器添加更多子parser?

Python 如何向argpare解析器添加更多子parser?,python,python-3.x,argparse,subparsers,Python,Python 3.x,Argparse,Subparsers,如果我的代码调用了一个函数,该函数返回一个已经定义了一些子parser的ArgumentParser,我如何添加更多的子parser sp = parser.add_subparsers(...) 我想这样做: parser_with_subparsers = build_parser() additional_subparsers = parser_with_subparsers.add_subparsers() extra_subparser = additional_subparsers

如果我的代码调用了一个函数,该函数返回一个已经定义了一些子parser的
ArgumentParser
,我如何添加更多的子parser

sp = parser.add_subparsers(...)
我想这样做:

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\u parser()
函数的内部

我能想到的唯一解决方案是使用
父项
,但这会产生副作用,即以一种奇怪的方式将子parser分组:

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

我之所以要这样做,是因为我想向继承的
参数解析器添加额外的“命令”。

您希望从添加的子解析器中获得什么样的行为

sp = parser.add_subparsers(...)
add_subparsers
创建
_subparseraction
类的位置参数,并在
解析器中记录它。_subparsers
属性。如果已设置该属性,则会引发该错误
sp
Action
对象

从逻辑上讲,有多个“下级”行动是没有意义的。当主解析器遇到子解析器命令时,它将解析委托给该子解析器。除了一些清除错误检查外,主解析器不会恢复解析。所以它无法处理第二个subparser命令

(有关
add_subparser
创建的内容和
add_parser
所做的工作的术语可能会令人困惑。一个是位置参数/动作,另一个是解析器(
ArgumentParser
的实例)

应该可以将新的解析器添加到现有的
子parser
操作中(我必须进行实验以找到一种干净的方法)。还可以添加嵌套子parser,即为子parser定义
add_子parser


parents
方法绕过了这个
多个子parser参数
测试,可能是因为它没有在第一次(从父对象复制操作时)设置
解析器。因此,实际上会创建两个
子parser参数
。这就是
帮助
所显示的。但我的猜测是,解析将没有意义。它仍然会使用“原始子parser”,而不会查找“extra”或“extra2”

父母
机制并不健壮。它有直接的用途,但很容易被破坏


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
\u 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)
因此,如果您只想将
extra
extra2
添加到
original\u subparser
,这应该可以实现

因此,只要我们不再尝试进一步的
解析器。添加参数(…)
抓取最后一个
\u操作
项就可以了。如果它不是最后一个,我们就必须进行更复杂的搜索

从我的rep更改判断,有人发现了早期对
\u subparsers
属性的探索:


谢谢。我有点担心在模块内部乱翻,但这似乎确实是唯一的方法!
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