argparse subparser monolithic help output

argparse, python

Solution

This is a bit tricky, as argparse does not expose a list of defined sub-parsers directly. But it can be done:

import argparse

# create the top-level parser
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--foo', action='store_true', help='foo help')
subparsers = parser.add_subparsers(help='sub-command help')

# create the parser for the "a" command
parser_a = subparsers.add_parser('a', help='a help')
parser_a.add_argument('bar', type=int, help='bar help')

# create the parser for the "b" command
parser_b = subparsers.add_parser('b', help='b help')
parser_b.add_argument('--baz', choices='XYZ', help='baz help')
# print main help
print(parser.format_help())

# retrieve subparsers from parser
subparsers_actions = [
    action for action in parser._actions 
    if isinstance(action, argparse._SubParsersAction)]
# there will probably only be one subparser_action,
# but better safe than sorry
for subparsers_action in subparsers_actions:
    # get all subparsers and print help
    for choice, subparser in subparsers_action.choices.items():
        print("Subparser '{}'".format(choice))
        print(subparser.format_help())

This example should work for python 2.7 and python 3. The example parser is from Python 2.7 documentation on argparse sub-commands.

The only thing left to do is adding a new argument for the complete help, or replacing the built in `-h/--help`.

Problem

My argparse has only 3 flags (store_true) on the top level, everything else is handled through subparsers. When I run `myprog.py --help`, the output shows a list of all subcommands like normal, `{sub1, sub2, sub3, sub4, ...}`. So, the default is working great... I usually can't remember the exact subcommand name I need, and all of its options. So I end up doing 2 help lookups: ``` myprog.py --help myprog.py sub1 --help ``` I do this so often, I decided to cram this into one step. I would rather have my toplevel help output a huge summary, and then I scroll through the list manually. I find it is much faster (for me at least). I was using a RawDescriptionHelpFormatter, and typing the long help output by hand. But now I have lots of subcommands, and its becoming a pain to manage. Is there a way to get a verbose help output with just one program call? If not, how can I iterate the subparsers of my argparse instance, and then retrieve the help output individually from each one (which I will then later glue together)? Here is a quick outline of my argparse setup. I cleaned/stripped the code a fair bit, so this may not run without a bit of help. ``` parser = argparse.ArgumentParser( prog='myprog.py', formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent(""" You can manually type Help here """) ) parser.add_argument('--debuglog', action='store_true', help='Verbose logging for debug purposes.') parser.add_argument('--ipyonexit', action='store_true', help='Drop into an embeded Ipython session instead of exiting command.') subparser = parser.add_subparsers() ### --- Subparser B parser_b = subparser.add_parser('pdfreport', description="Used to output reports in PDF format.") parser_b.add_argument('type', type=str, choices=['flatlist', 'nested', 'custom'], help="The type of PDF report to generate.") parser_b.add_argument('--of', type=str, default='', help="Override the path/name of the output file.") parser_b.add_argument('--pagesize', type=str, choices=['letter', '3x5', '5x7'], default='letter', help="Override page size in output PDF.") parser_b.set_defaults(func=cmd_pdf_report) ### ---- Subparser C parser_c = subparser.add_parser('dbtables', description="Used to perform direct DB import/export using XLS files.") parser_c.add_argument('action', type=str, choices=['push', 'pull', 'append', 'update'], help="The action to perform on the Database Tables.") parser_c.add_argument('tablename', nargs="+", help="The name(s) of the DB-Table to operate on.") parser_c.set_defaults(func=cmd_db_tables) args = parser.parse_args() args.func(args) ```

Original source

Related problems