Python argparse:如何分别获取参数组的命名空间对象?
Python argparse : How can I get Namespace objects for argument groups separately?
我有一些命令行参数分组如下:
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')
我如何解析以上内容,从而得到三个不同的命名空间对象?
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
谢谢!
argparse
中没有任何内容旨在做到这一点。
就其价值而言,parser
从两个参数组开始,一个显示为 positionals
,另一个显示为 optionals
(我忘记了确切的标题)。所以在你的例子中实际上会有 4 个组。
解析器在格式化帮助时仅使用参数组。为了解析,所有参数都放在主 parser._actions
列表中。在解析过程中,解析器只传递一个命名空间 object.
您可以使用不同的参数集定义单独的解析器,并使用 parse_known_args
调用每个解析器。使用 optionals
(标记的)参数比使用 positionals
效果更好。它会分散你的帮助。
我在其他 SO 问题中探索了一本小说 Namespace
class,它可以基于某种点缀 dest
(如 group1.optA
、group2.optC
,等等)。我不记得我是否必须自定义 Action
classes。
基本点是,当将值保存到命名空间、解析器或实际上 Action
(参数)object 时:
setattr(namespace, dest, value)
那(和 getattr/hasattr)是解析器对 namespace
的全部期望。默认的 Namespace
class 很简单,只不过是一个普通的 object
subclass。但它可以更详细。
你可以这样做:
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)
这将为您提供正常的参数,以及包含每个添加组的名称空间的字典 arg_groups。
(改编自)
我一直在寻找解决方案,
我想我终于明白了。
所以我就把它放在这里...
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)
你唯一不能用这个方法做的是将调试短标志一起传递给其他短标志:
ubuntu → playAround $ ./test.py -12d
usage: test.py [-h] [-1] [-2] [-3]
test.py: error: argument -2/--flag-2: ignored explicit argument 'd'
这是一个简单的方法,它在定义每个组后调用 parse_known_args()
方法以分别获取这些参数的名称。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('mainArg')
global_names = set(vars(parser.parse_known_args()[0]).keys())
group1 = parser.add_argument_group('group 1')
group1.add_argument('-optA')
group1.add_argument('-optB')
group1_names = set(vars(parser.parse_known_args()[0]).keys()) - global_names
group2 = parser.add_argument_group('group 2')
group2.add_argument('-optC')
group2.add_argument('-optD')
group2_names = set(vars(parser.parse_known_args()[0]).keys()) - global_names - group1_names
args = parser.parse_args()
global_args = argparse.Namespace(**dict((k, v) for k, v in vars(args).items() if k in global_names))
group1_args = argparse.Namespace(**dict((k, v) for k, v in vars(args).items() if k in group1_names))
group2_args = argparse.Namespace(**dict((k, v) for k, v in vars(args).items() if k in group2_names))
print(global_args)
print(group1_args)
print(group2_args)
例如python args.py hi -optA fooA -optB fooB -optC fooC -optD fooD
将输出:
Namespace(mainArg='hi')
Namespace(optA='fooA', optB='fooB')
Namespace(optC='fooC', optD='fooD')
我有一些命令行参数分组如下:
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')
我如何解析以上内容,从而得到三个不同的命名空间对象?
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
谢谢!
argparse
中没有任何内容旨在做到这一点。
就其价值而言,parser
从两个参数组开始,一个显示为 positionals
,另一个显示为 optionals
(我忘记了确切的标题)。所以在你的例子中实际上会有 4 个组。
解析器在格式化帮助时仅使用参数组。为了解析,所有参数都放在主 parser._actions
列表中。在解析过程中,解析器只传递一个命名空间 object.
您可以使用不同的参数集定义单独的解析器,并使用 parse_known_args
调用每个解析器。使用 optionals
(标记的)参数比使用 positionals
效果更好。它会分散你的帮助。
我在其他 SO 问题中探索了一本小说 Namespace
class,它可以基于某种点缀 dest
(如 group1.optA
、group2.optC
,等等)。我不记得我是否必须自定义 Action
classes。
基本点是,当将值保存到命名空间、解析器或实际上 Action
(参数)object 时:
setattr(namespace, dest, value)
那(和 getattr/hasattr)是解析器对 namespace
的全部期望。默认的 Namespace
class 很简单,只不过是一个普通的 object
subclass。但它可以更详细。
你可以这样做:
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)
这将为您提供正常的参数,以及包含每个添加组的名称空间的字典 arg_groups。
(改编自
我一直在寻找解决方案,
我想我终于明白了。
所以我就把它放在这里...
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)
你唯一不能用这个方法做的是将调试短标志一起传递给其他短标志:
ubuntu → playAround $ ./test.py -12d
usage: test.py [-h] [-1] [-2] [-3]
test.py: error: argument -2/--flag-2: ignored explicit argument 'd'
这是一个简单的方法,它在定义每个组后调用 parse_known_args()
方法以分别获取这些参数的名称。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('mainArg')
global_names = set(vars(parser.parse_known_args()[0]).keys())
group1 = parser.add_argument_group('group 1')
group1.add_argument('-optA')
group1.add_argument('-optB')
group1_names = set(vars(parser.parse_known_args()[0]).keys()) - global_names
group2 = parser.add_argument_group('group 2')
group2.add_argument('-optC')
group2.add_argument('-optD')
group2_names = set(vars(parser.parse_known_args()[0]).keys()) - global_names - group1_names
args = parser.parse_args()
global_args = argparse.Namespace(**dict((k, v) for k, v in vars(args).items() if k in global_names))
group1_args = argparse.Namespace(**dict((k, v) for k, v in vars(args).items() if k in group1_names))
group2_args = argparse.Namespace(**dict((k, v) for k, v in vars(args).items() if k in group2_names))
print(global_args)
print(group1_args)
print(group2_args)
例如python args.py hi -optA fooA -optB fooB -optC fooC -optD fooD
将输出:
Namespace(mainArg='hi')
Namespace(optA='fooA', optB='fooB')
Namespace(optC='fooC', optD='fooD')