I'm trying to achieve a program that makes both use of sub-commands (e.g.: program sub-command [options]) and groups (which makes for a fancy help dialog).
I have achieved this goal with one minor exception: In order to get the help dialog in its own group I must add the flag add_help=False
when creating the sub-command parser, which removes the help message when running the top-level help dialog (e.g.: program -h
).
Here's the code I've developed:
# imports
import argparse
# create the top-level parser
parser = argparse.ArgumentParser(prog="example", add_help=False, epilog="A very cool program")
# add top-level groups
toplevel = parser.add_argument_group("Global arguments")
toplevel.add_argument("-g", "--global", action="store_true", help="A global argument.")
help = parser.add_argument_group("Help dialog")
help.add_argument("-h", "--help", action="help", default=argparse.SUPPRESS, help="Show this help message and exit.")
# create subparser
subparsers = parser.add_subparsers(title="Available subcommands", dest="subcommand")
# create the parser for the "a" subcommand
parser_a = subparsers.add_parser("a", add_help=False)
# add groups for subcommand "a"
required_a = parser_a.add_argument_group("Required arguments")
required_a.add_argument("--bar", type=int, help="Flag bar help", required=True)
help_a = parser_a.add_argument_group("Help dialog")
help_a.add_argument("-h", "--help", action="help", default=argparse.SUPPRESS, help="Show this help message and exit.")
# create the parser for the "b" command
parser_b = subparsers.add_parser("b", add_help=False)
# add groups for subcommand "b"
required_b = parser_b.add_argument_group("Required arguments")
required_b.add_argument("--baz", help="Flag baz help", required=True)
optional_b = parser_b.add_argument_group("Optional arguments")
optional_b.add_argument("--tas", help="Flag tas help")
help_b = parser_b.add_argument_group("Help dialog")
help_b.add_argument("-h", "--help", action="help", default=argparse.SUPPRESS, help="Show this help message and exit.")
# parse arguments
args = parser.parse_args()
# provide args to main
print(args)
The top-level help is as follows:
$ example -h
usage: example [-g] [-h] {a,b} ...
Global arguments:
-g, --global A global argument.
Help dialog:
-h, --help Show this help message and exit.
Available sub-commands:
{a,b}
A very cool program
Which as you can see doesn't show the help message on the sub-commands.
To have them show up I would have to get rid of add_help=False
when creating parser_a
and parser_b
but then, as expected, it would raise an issue when I would define my own help flag.
Essentially I would like to have the best of both worlds, where my main dialog would be:
$ example -h
usage: example [-g] [-h] {a,b} ...
Global arguments:
-g, --global A global argument.
Help dialog:
-h, --help Show this help message and exit.
Available sub-commands:
{a,b}
a Help for sub-command a.
b Help for sub-command b.
A very cool program
And the sub-commands would be:
$ example a -h
usage: example a --bar BAR [-h]
Required arguments:
--bar BAR Flag bar help
Help dialog:
-h, --help Show this help message and exit.
After going through the argparse source code, would the option conflict_handler
be a possible solution? Would it be possible to tell it to ignore the original help dialog, which shows under positional arguments which I do not want, and have it instead showing in my own group but without disabling it completely?
TL;DR: Looking for modifications required to my Python script such that argparse outputs the two previous code blocks.
Note: The reason why "help-dialog" is written in the title is because stack overflow does not allow me to write the world "help" on the title, regardless of where it is written in the sentence.