2

I have a long list of parameters, so the output from mycommand --help is getting very big. I would like to provide my users a way to get the help text for only a specific parameter.

Something like this (doesn't work, shows the whole help text)

mycommand --help --parameter-of-interest

I don't want to split everything into subparsers if at all avoidable.

Alex
  • 6,610
  • 3
  • 20
  • 38
Cyberwiz
  • 11,027
  • 3
  • 20
  • 40

2 Answers2

2

You can create your own actions to achieve this. Both of these will iterate the optional arguments and suppress any that are not found in sys.argv. I'd recommend the explain action as this doesn't mess with the -h/--help flag.

Explain Action

This creates an action ExplainParamsAction with the corresponding -e/--explain options that filters the help text for just specified parameters.

import sys
import argparse

class ExplainParamsAction(argparse.Action):
    def __init__(
        self,
        option_strings,
        dest=argparse.SUPPRESS,
        default=argparse.SUPPRESS,
        **kwargs
    ):
        super().__init__(option_strings, dest, default=default, nargs=0, **kwargs)

    def __call__(self, parser, namespace, values, option_string=None):
        opts = parser._option_string_actions
        for arg in opts:
            if arg not in sys.argv:
                setattr(opts[arg], "help", argparse.SUPPRESS)
        parser.print_help()
        parser.exit()

parser = argparse.ArgumentParser()
parser.add_argument(
    "-e",
    "--explain",
    action=ExplainParamsAction,
    help="Show help message for only specified parameters and exit",
)
parser.add_argument("--url", help="URL to the resource")
parser.add_argument("--port", help="Port to the resource")
parser.add_argument("--timeout", help="Connection timeout")
args = parser.parse_args()

Override the Help Action

Alternatively you can override the help action that you supply to your parser. To use with an argparse.ArgumentParser you need to turn off the default helper and provide your own.

import sys
import argparse

class _CustomHelpAction(argparse._HelpAction):
    def __call__(self, parser, namespace, values, option_string=None):
        args = sys.argv[1:]
        opts = parser._option_string_actions
        # Check is needed for just -h/--help to work
        if len(args) > 1:
            for arg in opts:
                if arg not in args:
                    setattr(opts[arg], "help", argparse.SUPPRESS)
        super().__call__(parser, namespace, values, option_string)


# Init parser with help turned off
parser = argparse.ArgumentParser(add_help=False)

# Register your help action and manually add the `-h/--help` option
parser.register("action", "help", _CustomHelpAction)
parser.add_argument("-h", "--help", action="help", help="show this help message and exit")

# Add remaining arguments
parser.add_argument("--url", help="URL to the resource")
parser.add_argument("--port", help="Port to the resource")
parser.add_argument("--timeout", help="Connection timeout")
args = parser.parse_args()

Example usage:

All help:

python3 script.py --help
usage: script.py [-h] [--url URL] [--port PORT] [--timeout TIMEOUT]

optional arguments:
  -h, --help
  --url URL          URL to the resource
  --port PORT        Port to the resource
  --timeout TIMEOUT  Connection timeout

Specific parameters:

~ python3 script.py -h --url --timeout
usage: script.py [--url URL] [--timeout TIMEOUT]

optional arguments:
  --url URL          URL to the resource
  --timeout TIMEOUT  Connection timeout
~ python3 script.py -h --timeout --port
usage: script.py [--timeout TIMEOUT] [--port PORT]

optional arguments:
  --port PORT        Port to the resource
  --timeout TIMEOUT  Connection timeout

This naively assumes that you are only using sys.argv, I'm not really sure what would need to be done if it weren't.

Alex
  • 6,610
  • 3
  • 20
  • 38
  • 1
    Looking at Kilian's answer I think there may be a nice middle ground where you maintain the default `-h/--help` action and add a new action that explains parameters. – Alex Feb 23 '22 at 13:21
  • 1
    That could make sense too! An --arghelp command or something. – Cyberwiz Feb 23 '22 at 13:54
  • 1
    I've just added an `ExplainParamAction` example. I think the flag `--arg-help` is quite a good name for it – Alex Feb 23 '22 at 13:55
1

This has been discussed here: Customize argparse help message

In essence, you can overwrite the help by adding --help as argument.

Edit: the custom help could be pointing to a syntax for getting help on a specific parameter like -s parameter_you_wish_help_about.

Edit 2: Haven't tested it, but something along this lines.

parser.add_argument('-s',action='store',dest='para', type=str, help='Get Help on specific parameter')
parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help='Use -s to get help on specific parameter')

help_dict={}
help_dict['para_1']='Help on para_1'
print (help_dict[args.para])
Kilian
  • 468
  • 2
  • 9
  • That looks like it could work. That answer is a little complex though. Can you maybe help unpack it a little for my specific requirement? If it is that complicated to do then probably it isnt really worth it for me... – Cyberwiz Feb 23 '22 at 12:49