Python argparse:我如何单独获取参数组的Namespace对象?

时间:2016-08-10 22:23:05

标签: python argparse

我有一些按组分类的命令行参数如下:

cmdParser = argparse.ArgumentParser()
cmdParser.add_argument('mainArg')

groupOne = cmdParser.add_argument_group('group one')
groupOne.add_argument('-optA')
groupOne.add_argument('-optB')

groupTwo = cmdParser.add_argument_group('group two')
groupTwo.add_argument('-optC')
groupTwo.add_argument('-optD')

我如何解析上面的内容,以便最终得到三个不同的Namespace对象?

global_args - containing all the arguments not part of any group
groupOne_args - containing all the arguments in groupOne
groupTwo_args - containing all the arguments in groupTwo

谢谢!

3 个答案:

答案 0 :(得分:3)

你可以这样做:

import argparse
parser = argparse.ArgumentParser()

group1 = parser.add_argument_group('group1')
group1.add_argument('--test1', help="test1")

group2 = parser.add_argument_group('group2')
group2.add_argument('--test2', help="test2")

args = parser.parse_args('--test1 one --test2 two'.split())

arg_groups={}

for group in parser._action_groups:
    group_dict={a.dest:getattr(args,a.dest,None) for a in group._group_actions}
    arg_groups[group.title]=argparse.Namespace(**group_dict))

这将为您提供正常的args,以及包含每个已添加组的名称空间的字典arg_groups。

(改编自this answer

答案 1 :(得分:2)

argparse中的任何内容都不是为了做到这一点。

对于它的价值,parser从两个参数组开始,一个显示为positionals,另一个显示为optionals(我忘记确切的标题)。因此,在您的示例中,实际上将有4个组。

解析器仅在格式化帮助时使用参数组。对于解析,所有参数都放在主parser._actions列表中。在解析过程中,解析器只传递一个命名空间对象。

您可以使用不同的参数集定义单独的解析器,并使用parse_known_args调用每个解析器。使用optionals(标记)参数比使用positionals更好。它会破坏你的帮助。

我在其他SO问题中探讨过一个小小的Namespace类,它可以基于某种虚线destgroup1.optAgroup2.optC等名称)来嵌套值。 。我不记得是否必须自定义Action类。

基本点是,当将值保存到命名空间,解析器或实际上是Action(参数)对象时:

setattr(namespace, dest, value)

那个(和getattr / hasattr)是解析器对namespace所期望的全部。默认的Namespace类很简单,只是普通的object子类。但它可能更精细。

答案 2 :(得分:0)

很长时间以来,我一直在寻找解决方案,
我想我终于明白了。
所以我就把它放在这里...

from argparse import ArgumentParser

def _parse_args():
    parser = ArgumentParser()
    parser.add_argument('-1', '--flag-1', action='store_true', default=False)
    parser.add_argument('-2', '--flag-2', action='store_true', default=False)
    parser.add_argument('-3', '--flag-3', action='store_true', default=False)

    args, unknown = parser.parse_known_args()
    print(f"args        : {args}")
    print(f"unknown     : {unknown}")

    hidden = ArgumentParser(add_help=False)
    hidden.add_argument('-d', '--debug', action='store_true', default=False)
    hidden_args = hidden.parse_args(unknown)
    print(f"hidden_args : {hidden_args}")

if __name__ == "__main__":
    _parse_args()

结果:
显示帮助:

ubuntu → playAround $ ./test.py -h
usage: test.py [-h] [-1] [-2] [-3]

optional arguments:
  -h, --help    show this help message and exit
  -1, --flag-1
  -2, --flag-2
  -3, --flag-3

带有调试标志:

ubuntu → playAround $ ./test.py -d
args        : Namespace(flag_1=False, flag_2=False, flag_3=False)
unknown     : ['-d']
hidden_args : Namespace(debug=True)

带有标志1和2:

ubuntu → playAround $ ./test.py -12
args        : Namespace(flag_1=True, flag_2=True, flag_3=False)
unknown     : []
hidden_args : Namespace(debug=False)

带有标志1和2并进行调试:

ubuntu → playAround $ ./test.py -12 -d
args        : Namespace(flag_1=True, flag_2=True, flag_3=False)
unknown     : ['-d']
hidden_args : Namespace(debug=True)

您无法使用此方法做的唯一事情是将debug short标志与其他short标志一起传递:

ubuntu → playAround $ ./test.py -12d
usage: test.py [-h] [-1] [-2] [-3]
test.py: error: argument -2/--flag-2: ignored explicit argument 'd'