python - 带有嵌套命名空间的 argparse 子命令

标签 python namespaces argparse

是否argparse提供内置工具让它将组或解析器解析到它们自己的命名空间中?我觉得我一定是在某处遗漏了一个选项。

编辑:这个例子可能不是我应该做的来构建解析器来满足我的目标,但这是我到目前为止所做的。我的具体目标是能够为子解析器提供解析为命名空间字段的选项组。我和 parent 的想法只是为了同样的目的使用通用选项。

例子:

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

这显然是我得到的:

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

但这才是我真正想要的:

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

然后更多的选项组已经被解析到命名空间中:

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

我找到了 related question here但它涉及一些自定义解析,并且似乎只涵盖了真正特定的情况。

是否有某个选项可以告诉 argparse 将某些组解析为命名空间字段?

最佳答案

如果重点只是将选定的参数放在它们自己的 namespace 中,并且子解析器(和父级)的使用是偶然的问题,那么这个自定义操作可能会成功。

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 名称的方法有很多种。它可以在定义 Action 时作为参数传递。它可以作为参数添加。这里我选择从dest解析(这样namespace.filter.filter1可以得到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 条目就不会出现在主命名空间中。

结果:

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

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

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

结果和以前一样,除了:

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

关于python - 带有嵌套命名空间的 argparse 子命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18668227/

相关文章:

php - 关于一个简单的 PHP Autoloader 的问题

laravel - 在 Laravel View 中使用命名空间

python - 对带有字典的 Python 命名空间感到好奇

python - 理解python的argparse模块

Python 名称错误 : name 'file_name' is not defined

python - 我们如何使用 Chef 连接基于集群的软件?

python - SSL: CERTIFICATE_VERIFY_FAILED] 从 python 脚本生成 SMS 时证书验证失败

python:在父类的方法中,调用该类的类方法,但绑定(bind)到子类

python - 随机行走 Pandas

python - 如何在 argparse 中将子解析器设置为可选?