I'm looking to do something like this:
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")
group1_args = group1.parse_args()
group2_args = group2.parse_args()
However, I'm getting the following error:
Traceback (most recent call last):
File "test.py", line 19, in <module>
group1_args = group1.parse_args()
AttributeError: '_ArgumentGroup' object has no attribute 'parse_args'
Is there a way to only get the arguments for one argument group?
As your error message indicates, an ArgumentGroup is not a parser, specifically it doesn't have the parse_args
method.
ArgumentParser objects and ArgumentGroup objects share a base ArgumentContainer class that gives them methods like add_argument
. But an ArgumentParser has a lot of additional code. An ArgumentGroup is really just an aid in formatting the help
. It does not affect parsing in any way.
To add confusion, a mutually_exclusive_group
subclasses ArgumentGroup
, but affects only the usage
part of the help
, and affects parsing by raising an error message.
If you elaborate on why you want to do this, we could come up with some alternatives that might work. For example there is a parents
mechanism, that lets you insert
one parser
into another. Or subparsers
that pass parsing control to a subparsers via 'command' arguments.
https://docs.python.org/3/library/argparse.html#parents
Defining each group in its own parent
parser, would let you control both the help display, and parsing. Only problem with parents is that you have to use help=False
at some level to prevent the duplication of the -h
option.
You may also need to use parse_known_args
so the 'group' parser does not complain about arguments that it does not recognize.
Here's a way of displaying all the args
entries, grouped by argument group. I'm including the 2 default groups, optionals and positionals. It does make use of 'private' attributes of the parser. There's a bit of risk in doing so, but this isn't the kind of thing that is likely to be changed in future patches.
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())
print([g.title for g in parser._action_groups]) # all group titles
print(group1._group_actions) # arguments/actions of `group1`
print([a.dest for a in group2._group_actions]) # actions for group2
for group in parser._action_groups:
group_dict={a.dest:getattr(args,a.dest,None) for a in group._group_actions}
print(group.title, argparse.Namespace(**group_dict))
producing
1513:~/mypy$ python stack31519997.py
['positional arguments', 'optional arguments', 'group1', 'group2']
[_StoreAction(option_strings=['--test1'], dest='test1', nargs=None, const=None, default=None, type=None, choices=None, help='test1', metavar=None)]
['test2']
('positional arguments', Namespace())
('optional arguments', Namespace(help=None))
('group1', Namespace(test1='one'))
('group2', Namespace(test2='two'))
If could be more convenient to work with vars(args)
, the dictionary version. argparse.Namespace(**adict)
recreates a namespace from a dictionary.
Of coarse you make your own dest
lists, ['test1']
and ['test2']
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With