0

I would like to add groups in a subparser.

parser = argparse.ArgumentParser(description="A Pipeline.")
subparsers = parser.add_subparsers(
    help="Choose imagery source", dest="imagery_source"
)

animal_parser = subparsers.add_parser("animal")
group1_parser = animal_parser.add_argument_group("for_dog_config")
group1_parser.add_argument("--dog", type=str)

group2_parser = animal_parser.add_argument_group("for_cat_config")
group2_parser.add_argument("--cat", type=str)

args = parser.parse_args()
print(args)

run_pipeline animal --dog hello --cat world
Here is the output of namespace.

Namespace(cat='world', dog='hello', imagery_source='animal')

What I would like is that the cat and dog are in different namespaces or dictionaries respectively. Is it possible? Note: I know there are other answers using add_argument_group in ArgumentParser object, but I need to use subparsers = prser.add_subparsers here.

=========== Update ===========
This code block almost do what I need.

def get_arg(parser):
    args = parser.parse_args()
    args_groups = {}
    for group in parser._action_groups:
        group_dict = {a.dest: getattr(args, a.dest, None) for a in group._group_actions}
        args_groups.update({group.title: argparse.Namespace(**group_dict)})
    return args_groups

parser = argparse.ArgumentParser(description="A Pipeline.")
subparsers = parser.add_subparsers(
    help="Choose imagery source", dest="imagery_source"
)
group1_parser = parser.add_argument_group("for_dog_config")
group1_parser.add_argument("--dog", type=str)

group2_parser = parser.add_argument_group("for_cat_config")
group2_parser.add_argument("--cat", type=str)

args = get_arg(parser)
print(args)

Execute run_stereo_pipeline --dog hello --cat world The output is

{'positional arguments': Namespace(imagery_source=None), 'optional arguments': Namespace(help=None), 'for_dog_config': Namespace(dog='hello'), 'for_cat_config': Namespace(cat='world')}

As you can see, now I can do things like args["for_cat_config"] to get all arguments in the "for_cat_config" group. But in this approach, I can not specify animal source which is what I want in the question.

Lion Lai
  • 1,862
  • 2
  • 20
  • 41
  • `add_argument_group` for `animal_parser` works the same as for `parser`. `subparsers` is a special `Action` object, but `animal_parser` is a parser, just like the main. That said, argument_groups only group the help lines; they don't affect parsing. – hpaulj Jul 14 '21 at 06:16
  • What other answers do you have in mind? I have explored creating subdirectories or namespaces within in the main namespace, but it requires some special games with the `argparse.Namespace` class, or with the argument `Action` subclass. I don't `argument_groups` help with that. – hpaulj Jul 14 '21 at 06:22
  • https://stackoverflow.com/questions/66831906/update-argparse-namespace-with-other-namespace-dictionary explains the relation between the subparser's namespace and the main parser's - values are just copied from one to the other. – hpaulj Jul 14 '21 at 06:29
  • https://stackoverflow.com/questions/38884513/python-argparse-how-can-i-get-namespace-objects-for-argument-groups-separately - an example of how convoluted it is to create separate namespace objects. Or https://stackoverflow.com/questions/18668227/argparse-subcommands-with-nested-namespaces – hpaulj Jul 14 '21 at 06:31
  • @hpaulj Thanks for your reply. But I have read through the link you provide which does not really help in my case, unfortunately. Btw, I update my question. Please take a look. Thanks. – Lion Lai Jul 14 '21 at 06:40
  • You'll have to look in `animal_parser._action_groups`. `parser` doesn't have access to the groups in the other parsers. Or you could have a separate list or dict of `dest` that you want to group separately. Using `_action_groups` for this purpose might be more work than it's worth. This regrouping is outside of the `argparse` proper, so can be done in whatever way is programmatically convenient. – hpaulj Jul 14 '21 at 07:12

0 Answers0