如何从父解析器获取 argparse 子解析器(检查默认值)
How to obtain argparse subparsers from a parent parser (to inspect defaults)
假设我创建了一个带有默认参数值的解析器,然后给它一个带有另一个参数默认值的子解析器。
In [1]: parser = argparse.ArgumentParser(description='test')
In [2]: parser.add_argument("--test", dest="test", default="hello")
Out[2]: _StoreAction(option_strings=['--test'], dest='test', nargs=None, const=None, default='hello', type=None, choices=None, help=None, metavar=None)
In [3]: parser.get_default("test")
Out[3]: 'hello'
In [4]: subparsers = parser.add_subparsers(dest="command")
In [5]: parser_other = subparsers.add_parser("other")
In [6]: parser_other.add_argument("--other-test", dest="other_test", default="world")
Out[6]: _StoreAction(option_strings=['--other-test'], dest='other_test', nargs=None, const=None, default='world', type=None, choices=None, help=None, metavar=None)
In [7]: parser_other.get_default("other_test")
Out[7]: 'world'
这一切都很好。但是假设我有一个函数可以从上面创建和 returns 父解析器 parser
,但不能直接访问子解析器。
我怎样才能打印出子解析器参数的默认值?或者分别获取每个子解析器的句柄?
In [8]: parser._subparsers._defaults
Out[8]: {}
In [9]: parser._subparsers.get_default("other_test") # is None
parser._subparsers
或 parser
中似乎没有更多可以显示默认值的属性或方法。
总体问题是:当您只有父解析器的句柄时,如何以编程方式访问子解析器默认值?
基于this answer,看起来可以按如下方式完成:
subparsers = [
subparser
for action in parser._actions
if isinstance(action, argparse._SubParsersAction)
for _, subparser in action.choices.items()
]
然后
subparsers[0].get_default("other_test")
按预期打印 "world"
。
你没看错。但也许我可以解释一些细节。
a = parser.add_argument(...)
add_argument
创建一个 Action
object (或者实际上是一个 subclass 取决于 action
参数)。您可以在自己的环境中保存指向 object 的指针。但是该 Action 也收集在 parse._actions
列表中。这就是 parser
跟踪其参数的方式。
阅读_actions
应该总是安全的。修改它有破坏解析器的风险。 argument_groups
可以访问列表。
subparsers = parser.add_subparsers(dest="command")
是 add_argument
的特殊版本,创建并返回 argparse._SubParsersAction
object。 subparsers
就是 object。正如前面的答案所述,您可以通过搜索正确的 subclass 在 _actions
列表中找到它。 (对于主解析器,subparsers
只是另一个位置参数。)
subparsers
维护自己的 parsers
专用字典,可通过其 choices
属性访问。主解析器没有这些子解析器的任何记录。
parser_other = subparsers.add_parser("other")
创建一个解析器,将其放入 choices
映射中,并 returns 供您自己使用的参考(使用 add_argument
等)。每个子解析器都有自己的 _actions
列表。 (以及它自己的 _defaults
)。
查看get_defaults
方法的代码:
def get_default(self, dest):
for action in self._actions:
if action.dest == dest and action.default is not None:
return action.default
return self._defaults.get(dest, None)
它使用 _actions
属性。并查看 Action 的 action.default
属性。
self._defaults
是parser.set_defaults
方法更新的字典。该方法还将其参数复制到相关的 Action objects。 get_defaults
检查以防 dest
是未绑定到特定操作的默认值之一。 https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.set_defaults
我没怎么用过 parser._subparsers
属性。查看 parser.add_subparsers
方法,我发现它实际上是一个 argument_group
。 Argument_groups 主要是一个 help
工具,用于对帮助热线进行分组。解析器 object 和它的 argument_groups 之间的关系有点棘手,可能不是您想使用的东西。
这是一个例子,有更多(太多)细节:
In [22]: parser = argparse.ArgumentParser()
In [23]: sp = parser.add_subparsers(title='subparsers', dest='cmd')
In [24]: sp1 = sp.add_parser('cmd1')
In [25]: sp2 = sp.add_parser('cmd2')
In [26]: parser.print_help()
usage: ipython3 [-h] {cmd1,cmd2} ...
optional arguments:
-h, --help show this help message and exit
subparsers:
{cmd1,cmd2}
In [28]: [a.dest for a in parser._actions]
Out[28]: ['help', 'cmd']
In [29]: parser._action_groups
Out[29]:
[<argparse._ArgumentGroup at 0xaf86bf2c>,
<argparse._ArgumentGroup at 0xaf86bdcc>,
<argparse._ArgumentGroup at 0xac99fa6c>]
In [30]: [g.title for g in parser._action_groups]
Out[30]: ['positional arguments', 'optional arguments', 'subparsers']
In [31]: parser._subparsers
Out[31]: <argparse._ArgumentGroup at 0xac99fa6c>
_subparsers
的_defaults
其实和parser._defaults
是同一个字典
In [32]: parser.set_defaults(extra='foobar')
In [33]: parser._defaults
Out[33]: {'extra': 'foobar'}
In [34]: parser._subparsers._defaults
Out[34]: {'extra': 'foobar'}
parser._subparsers._actions
也等同于 parser._actions
。但是该组确实维护自己的列表操作(用于帮助显示)。
In [35]: parser._subparsers._group_actions
Out[35]: [_SubParsersAction(option_strings=[], dest='cmd', nargs='A...', const=None,
default=None, type=None, choices=OrderedDict([...]), help=None, metavar=None)]
因此您可以使用 parser._subparsers._group_actions[0]
查找 subparsers
操作 object 而不是搜索 parsers._actions
列表。
In [37]: parser._subparsers._group_actions[0].choices
Out[37]:
OrderedDict([('cmd1',
ArgumentParser(prog='ipython3 cmd1', usage=None, description=None,...)),
('cmd2',
ArgumentParser(prog='ipython3 cmd2', usage=None, description=None,...))])
转念一想,parser._subparsers._group_actions
可能没那么有用。如果你不给它一个特殊的标题,那么它就等同于parser._positionals
,所有位置参数的参数组。所以你仍然需要验证 _SubParsersAction
class.
假设我创建了一个带有默认参数值的解析器,然后给它一个带有另一个参数默认值的子解析器。
In [1]: parser = argparse.ArgumentParser(description='test')
In [2]: parser.add_argument("--test", dest="test", default="hello")
Out[2]: _StoreAction(option_strings=['--test'], dest='test', nargs=None, const=None, default='hello', type=None, choices=None, help=None, metavar=None)
In [3]: parser.get_default("test")
Out[3]: 'hello'
In [4]: subparsers = parser.add_subparsers(dest="command")
In [5]: parser_other = subparsers.add_parser("other")
In [6]: parser_other.add_argument("--other-test", dest="other_test", default="world")
Out[6]: _StoreAction(option_strings=['--other-test'], dest='other_test', nargs=None, const=None, default='world', type=None, choices=None, help=None, metavar=None)
In [7]: parser_other.get_default("other_test")
Out[7]: 'world'
这一切都很好。但是假设我有一个函数可以从上面创建和 returns 父解析器 parser
,但不能直接访问子解析器。
我怎样才能打印出子解析器参数的默认值?或者分别获取每个子解析器的句柄?
In [8]: parser._subparsers._defaults
Out[8]: {}
In [9]: parser._subparsers.get_default("other_test") # is None
parser._subparsers
或 parser
中似乎没有更多可以显示默认值的属性或方法。
总体问题是:当您只有父解析器的句柄时,如何以编程方式访问子解析器默认值?
基于this answer,看起来可以按如下方式完成:
subparsers = [
subparser
for action in parser._actions
if isinstance(action, argparse._SubParsersAction)
for _, subparser in action.choices.items()
]
然后
subparsers[0].get_default("other_test")
按预期打印 "world"
。
你没看错。但也许我可以解释一些细节。
a = parser.add_argument(...)
add_argument
创建一个 Action
object (或者实际上是一个 subclass 取决于 action
参数)。您可以在自己的环境中保存指向 object 的指针。但是该 Action 也收集在 parse._actions
列表中。这就是 parser
跟踪其参数的方式。
阅读_actions
应该总是安全的。修改它有破坏解析器的风险。 argument_groups
可以访问列表。
subparsers = parser.add_subparsers(dest="command")
是 add_argument
的特殊版本,创建并返回 argparse._SubParsersAction
object。 subparsers
就是 object。正如前面的答案所述,您可以通过搜索正确的 subclass 在 _actions
列表中找到它。 (对于主解析器,subparsers
只是另一个位置参数。)
subparsers
维护自己的 parsers
专用字典,可通过其 choices
属性访问。主解析器没有这些子解析器的任何记录。
parser_other = subparsers.add_parser("other")
创建一个解析器,将其放入 choices
映射中,并 returns 供您自己使用的参考(使用 add_argument
等)。每个子解析器都有自己的 _actions
列表。 (以及它自己的 _defaults
)。
查看get_defaults
方法的代码:
def get_default(self, dest):
for action in self._actions:
if action.dest == dest and action.default is not None:
return action.default
return self._defaults.get(dest, None)
它使用 _actions
属性。并查看 Action 的 action.default
属性。
self._defaults
是parser.set_defaults
方法更新的字典。该方法还将其参数复制到相关的 Action objects。 get_defaults
检查以防 dest
是未绑定到特定操作的默认值之一。 https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.set_defaults
我没怎么用过 parser._subparsers
属性。查看 parser.add_subparsers
方法,我发现它实际上是一个 argument_group
。 Argument_groups 主要是一个 help
工具,用于对帮助热线进行分组。解析器 object 和它的 argument_groups 之间的关系有点棘手,可能不是您想使用的东西。
这是一个例子,有更多(太多)细节:
In [22]: parser = argparse.ArgumentParser()
In [23]: sp = parser.add_subparsers(title='subparsers', dest='cmd')
In [24]: sp1 = sp.add_parser('cmd1')
In [25]: sp2 = sp.add_parser('cmd2')
In [26]: parser.print_help()
usage: ipython3 [-h] {cmd1,cmd2} ...
optional arguments:
-h, --help show this help message and exit
subparsers:
{cmd1,cmd2}
In [28]: [a.dest for a in parser._actions]
Out[28]: ['help', 'cmd']
In [29]: parser._action_groups
Out[29]:
[<argparse._ArgumentGroup at 0xaf86bf2c>,
<argparse._ArgumentGroup at 0xaf86bdcc>,
<argparse._ArgumentGroup at 0xac99fa6c>]
In [30]: [g.title for g in parser._action_groups]
Out[30]: ['positional arguments', 'optional arguments', 'subparsers']
In [31]: parser._subparsers
Out[31]: <argparse._ArgumentGroup at 0xac99fa6c>
_subparsers
的_defaults
其实和parser._defaults
In [32]: parser.set_defaults(extra='foobar')
In [33]: parser._defaults
Out[33]: {'extra': 'foobar'}
In [34]: parser._subparsers._defaults
Out[34]: {'extra': 'foobar'}
parser._subparsers._actions
也等同于 parser._actions
。但是该组确实维护自己的列表操作(用于帮助显示)。
In [35]: parser._subparsers._group_actions
Out[35]: [_SubParsersAction(option_strings=[], dest='cmd', nargs='A...', const=None,
default=None, type=None, choices=OrderedDict([...]), help=None, metavar=None)]
因此您可以使用 parser._subparsers._group_actions[0]
查找 subparsers
操作 object 而不是搜索 parsers._actions
列表。
In [37]: parser._subparsers._group_actions[0].choices
Out[37]:
OrderedDict([('cmd1',
ArgumentParser(prog='ipython3 cmd1', usage=None, description=None,...)),
('cmd2',
ArgumentParser(prog='ipython3 cmd2', usage=None, description=None,...))])
转念一想,parser._subparsers._group_actions
可能没那么有用。如果你不给它一个特殊的标题,那么它就等同于parser._positionals
,所有位置参数的参数组。所以你仍然需要验证 _SubParsersAction
class.