带有嵌套名称空间的argparse子命令 [英] argparse subcommands with nested namespaces

查看:103
本文介绍了带有嵌套名称空间的argparse子命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

argparse 是否提供内置功能来解析组或解析器进入自己的名称空间?我觉得我一定在某个地方错过了一个选择.

Does argparse provide built-in facilities for having it parse groups or parsers into their own namespaces? I feel like I must be missing an option somewhere.

编辑:这个示例可能不完全是我为构造解析器以满足我的目标而应该做的事情,但这是我到目前为止的工作.我的特定目标是能够为子解析器组提供选项组,这些选项组被解析为名称空间字段.我和父母的想法仅仅是出于相同的目的而使用通用选项.

Edit: This example is probably not exactly what I should be doing to structure the parser to meet my goal, but it was what I worked out so far. My specific goal is to be able to give subparsers groups of options that are parsed into namespace fields. The idea I had with parent was simply to use common options for this same purpose.

示例:

import argparse

# Main parser
main_parser = argparse.ArgumentParser()
main_parser.add_argument("-common")

# filter parser
filter_parser = argparse.ArgumentParser(add_help=False)
filter_parser.add_argument("-filter1")
filter_parser.add_argument("-filter2")

# sub commands
subparsers = main_parser.add_subparsers(help='sub-command help')

parser_a = subparsers.add_parser('command_a', help="command_a help", parents=[filter_parser])
parser_a.add_argument("-foo")
parser_a.add_argument("-bar")

parser_b = subparsers.add_parser('command_b', help="command_b help", parents=[filter_parser])
parser_b.add_argument("-biz")
parser_b.add_argument("-baz")

# parse
namespace = main_parser.parse_args()
print namespace

这就是我得到的,显然:

This is what I get, obviously:

$ python test.py command_a -foo bar -filter1 val
Namespace(bar=None, common=None, filter1='val', filter2=None, foo='bar')

但这就是我真正追求的:

But this is what I am really after:

Namespace(bar=None, common=None, foo='bar', 
          filter=Namespace(filter1='val', filter2=None))

然后更多的选项组已经解析为名称空间:

And then even more groups of options already parsed into namespaces:

Namespace(common=None, 
          foo='bar', bar=None,  
          filter=Namespace(filter1='val', filter2=None),
          anotherGroup=Namespace(bazers='val'),
          anotherGroup2=Namespace(fooers='val'),
          )

我找到了相关问题这里,但是它涉及一些自定义解析,似乎只涵盖了一个非常具体的情况.

I've found a related question here but it involves some custom parsing and seems to only covers a really specific circumstance.

在某处是否可以告诉argparse将某些组解析为命名空间的字段?

Is there an option somewhere to tell argparse to parse certain groups into namespaced fields?

推荐答案

如果重点是仅将选定的参数放在自己的namespace中,并且使用辅助解析器(和父级)是该问题的附带内容,行动可能会成功.

If the focus is on just putting selected arguments in their own namespace, and the use of subparsers (and parents) is incidental to the issue, this custom action might do the trick.

class GroupedAction(argparse.Action):    
    def __call__(self, parser, namespace, values, option_string=None):
        group,dest = self.dest.split('.',2)
        groupspace = getattr(namespace, group, argparse.Namespace())
        setattr(groupspace, dest, values)
        setattr(namespace, group, groupspace)

有多种方法指定group名称.定义操作时,可以将其作为参数传递.可以将其添加为参数.在这里,我选择从dest解析它(以便namespace.filter.filter1可以获取filter.filter1的值.

There are various ways of specifying the group name. It could be passed as an argument when defining the Action. It could be added as parameter. Here I chose to parse it from the dest (so namespace.filter.filter1 can get the value of filter.filter1.

# Main parser
main_parser = argparse.ArgumentParser()
main_parser.add_argument("-common")

filter_parser = argparse.ArgumentParser(add_help=False)
filter_parser.add_argument("--filter1", action=GroupedAction, dest='filter.filter1', default=argparse.SUPPRESS)
filter_parser.add_argument("--filter2", action=GroupedAction, dest='filter.filter2', default=argparse.SUPPRESS)

subparsers = main_parser.add_subparsers(help='sub-command help')

parser_a = subparsers.add_parser('command_a', help="command_a help", parents=[filter_parser])
parser_a.add_argument("--foo")
parser_a.add_argument("--bar")
parser_a.add_argument("--bazers", action=GroupedAction, dest='anotherGroup.bazers', default=argparse.SUPPRESS)
...
namespace = main_parser.parse_args()
print namespace

我必须添加default=argparse.SUPPRESS,所以bazers=None条目不会出现在主命名空间中.

I had to add default=argparse.SUPPRESS so a bazers=None entry does not appear in the main namespace.

结果:

>>> python PROG command_a --foo bar --filter1 val --bazers val
Namespace(anotherGroup=Namespace(bazers='val'), 
    bar=None, common=None, 
    filter=Namespace(filter1='val'), 
    foo='bar')

如果需要嵌套名称空间中的默认条目,则可以先定义名称空间:

If you need default entries in the nested namespaces, you could define the namespace before hand:

filter_namespace = argparse.Namespace(filter1=None, filter2=None)
namespace = argparse.Namespace(filter=filter_namespace)
namespace = main_parser.parse_args(namespace=namespace)

与以前一样的结果,除了:

result as before, except for:

filter=Namespace(filter1='val', filter2=None)

这篇关于带有嵌套名称空间的argparse子命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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