首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从父解析器获得a解析子解析器(检查默认值)

如何从父解析器获得a解析子解析器(检查默认值)
EN

Stack Overflow用户
提问于 2017-04-28 20:32:12
回答 2查看 3.6K关注 0票数 1

假设我为一个参数创建了一个默认值的解析器,然后给它一个带有参数的进一步默认值的子解析器。

代码语言:javascript
运行
复制
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'

这一切都很好。但是假设我有一个函数,它从上面创建并返回父解析器parser,但是没有对子解析器的直接访问。

如何仍然打印子解析器参数的默认值?还是分别获得每个子解析器的句柄?

代码语言:javascript
运行
复制
In [8]: parser._subparsers._defaults
Out[8]: {}

In [9]: parser._subparsers.get_default("other_test")  # is None

似乎没有更多的属性或方法可以从parser._subparsersparser中显示默认值。

总体问题是:当您只有父解析器的句柄时,如何以编程方式访问子解析器默认值?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-28 23:02:44

你做得对。但也许我能解释几个细节。

代码语言:javascript
运行
复制
a = parser.add_argument(...)

add_argument创建一个Action对象(或者实际上是一个子类,具体取决于action参数)。您可以在您自己的环境中保存指向该对象的指针。但是该操作也被收集在parse._actions列表中。这就是parser如何跟踪其论点。

阅读_actions应该始终是安全的。修改它可能会破坏解析器。argument_groups有权访问列表。

代码语言:javascript
运行
复制
subparsers = parser.add_subparsers(dest="command")

add_argument的专门版本,它创建并返回一个argparse._SubParsersAction对象。subparsers就是那个物体。正如前面的答案所指出的,您可以通过搜索正确的子类在_actions列表中找到它。(对于主解析器来说,subparsers只是另一个位置参数。)

subparsers维护自己的parsers专用字典,可作为choices属性访问。主解析器没有这些子解析器的任何记录。

代码语言:javascript
运行
复制
parser_other = subparsers.add_parser("other")

创建一个解析器,将其放入choices映射中,并返回一个引用供您自己使用(使用add_argument等)。每个子解析器都有自己的_actions列表。(以及它自己的_defaults)。

查看get_defaults方法的代码:

代码语言:javascript
运行
复制
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对象。get_defaults检查是否dest是与特定操作无关的默认设置之一。defaults

我没有经常使用parser._subparsers属性。看一下parser.add_subparsers方法,我看到它实际上是一个argument_group。Argument_groups主要是一个help工具,用于分组帮助热线。解析器对象与其argument_groups之间的关系有点棘手,可能不是您想要使用的东西。

下面是一个例子,其中包含了更多(太多)细节:

代码语言:javascript
运行
复制
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>

_defaults of _subparsers实际上是与parser._defaults相同的字典。

代码语言:javascript
运行
复制
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相同。但是这个组确实维护了它自己的列表操作(在帮助显示中使用)。

代码语言:javascript
运行
复制
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操作对象,而不是搜索parsers._actions列表。

代码语言:javascript
运行
复制
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类。

票数 6
EN

Stack Overflow用户

发布于 2017-04-28 20:46:08

基于this answer,它看起来可以这样做:

代码语言:javascript
运行
复制
subparsers = [
    subparser 
    for action in parser._actions 
    if isinstance(action, argparse._SubParsersAction) 
    for _, subparser in action.choices.items()
]

然后

代码语言:javascript
运行
复制
subparsers[0].get_default("other_test")

按预期打印"world"

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43688450

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档