如何从父解析器获取argparse子解析器(以检查默认值) [英] How to obtain argparse subparsers from a parent parser (to inspect defaults)

查看:76
本文介绍了如何从父解析器获取argparse子解析器(以检查默认值)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我创建了一个解析器,其参数为默认值,然后为它提供了一个子解析器,其参数为默认值.

Suppose that I create a parser with a default value for an argument, and then give it a subparser with a further default value for an argument.

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,但是不能直接访问子解析器.

This is all fine. But suppose that I have a function which creates and returns the parent parser parser from above, but with no direct access to the subparser.

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

How can I still print out defaults for the subparser arguments? Or get a handle to each subparser separately?

In [8]: parser._subparsers._defaults
Out[8]: {}

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

parser._subparsersparser中似乎没有其他属性或方法可以显示默认值.

There doesn't appear to be any more attributes or methods from parser._subparsers or from parser that could display defaults.

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

The overall problem is: how to programmatically access subparser defaults when you only have a handle to the parent parser?

推荐答案

您说对了.但是也许我可以解释一些细节.

You got it right. But maybe I can explain a few details.

a = parser.add_argument(...)

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

add_argument creates an Action object (or actually a subclass depending on the action parameter). You can save a pointer to that object in your own environment. But that Action is also collected in the parse._actions list. That's how the parser keeps tracks of its arguments.

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

Reading _actions should always be safe. Modifying it risks breaking breaking the parser. argument_groups have access to the list.

subparsers = parser.add_subparsers(dest="command")

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

is a specialized version of add_argument, creating and returning a argparse._SubParsersAction object. subparsers is that object. And as noted from the earlier answer, you can find it in the _actions list by searching for the correct subclass. (To the main parser, subparsers is just another positional argument.)

subparsers维护其自己的parsers专业词典,可以将其作为choices属性访问.主解析器没有这些子解析器的任何记录.

subparsers maintains its own specialized dictionary of parsers, accessible as its choices attribute. The main parser does not have any record of those sub parsers.

parser_other = subparsers.add_parser("other")

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

creates a parser, puts it in that choices map, and returns a reference for your own use (with add_argument etc). Each sub parser has its own _actions list. (and its own _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属性.

It uses the _actions attribute. And looks at the action.default attribute of the Action.

self._defaults是通过parser.set_defaults方法更新的词典.该方法还将其参数复制到相关的Action对象. get_defaults检查以确保dest是与特定操作无关的默认值之一. https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.set_defaults

self._defaults is the dictionary updated by the parser.set_defaults method. That method also copies its parameters to the relevant Action objects. get_defaults checks that in case the dest is one of those defaults that isn't tied to a particular Action. https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.set_defaults

我没有太多使用parser._subparsers属性.查看parser.add_subparsers方法,我发现它实际上是一个argument_group. Argument_groups主要是一个help工具,用于对帮助行进行分组.解析器对象及其argument_groups之间的关系有些棘手,并且可能不是您要使用的对象.

I haven't used the parser._subparsers attribute much. Looking at the parser.add_subparsers method I see it is actually an argument_group. Argument_groups are primarily a help tool, used to group help lines. The relationship between a parser object and its argument_groups is a little tricky, and probably not something you want to use.

下面是一个示例,其中包含(太多)详细信息:

Here's an example, with more (too much) detail:

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相同的字典

The _defaults of _subparsers is actually the same dictionary as 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相同.但是该组确实会维护自己的列表操作(在帮助显示中使用).

parser._subparsers._actions is also identical to parser._actions. But the group does maintain its own list actions (used in the help display).

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列表.

So you could use parser._subparsers._group_actions[0] to find the subparsers action object instead of searching the parsers._actions list.

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

On second thought, parser._subparsers._group_actions might not be so useful. If you don't give it a special title, then it is identical to parser._positionals, the argument group of all positional arguments. So you'd still need to verify the _SubParsersAction class.

这篇关于如何从父解析器获取argparse子解析器(以检查默认值)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆