finefoot
finefoot

Reputation: 11224

How to keep the automatically added argparse help argument, but remove -h from it so I can use that option for another argument

The automatically added help argument has option strings -h and --help. I want to keep the help argument for --help but remove -h from it, so I can use that option string for another argument.

I think there has to be a better way than to completely remove the help argument with add_help=False just to add it again with --help and action="help" immediately afterwards, right? Maybe I can modify the existing help argument's option strings?


By the way, regarding "Don't remove -h because users expect it to be an alias for --help": That's a fair argument. However, while having a quick look through my local binaries, I couldn't find any command which uses -h to show the help message other than fdisk. (That doesn't mean that there aren't a few more, of course.) Even more: Many commands use -h for something completely different, see ls, cd, df and diff to name some of them.

Upvotes: 5

Views: 624

Answers (2)

finefoot
finefoot

Reputation: 11224

Maybe I can modify the existing help argument's option strings?

Just to mention it, very hacky way to modify the existing arguments:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.print_help()
usage: [-h]

optional arguments:
  -h, --help  show this help message and exit
>>> parser._actions[0].option_strings.remove("-h")
>>> parser._option_string_actions.pop("-h")
_HelpAction(option_strings=['--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None)
>>> parser.print_help()
usage: [--help]

optional arguments:
  --help  show this help message and exit

By the way, instead of

parser._actions[0].option_strings.remove("-h")
parser._option_string_actions.pop("-h")

you could also make use of _handle_conflict_resolve:

parser._handle_conflict_resolve(None, [("-h", parser._actions[0])])

I think there has to be a better way than to completely remove the help argument with add_help=False just to add it again with --help and action="help" immediately afterwards

And just for completeness, here is how that would work:

>>> from argparse import ArgumentParser, SUPPRESS
>>> parser = ArgumentParser(add_help=False)
>>> parser.add_argument("--help", action="help", default=SUPPRESS, help="show this help message and exit")
_HelpAction(option_strings=['--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None)
>>> parser.print_help()
usage: [--help]

optional arguments:
  --help  show this help message and exit

Upvotes: 2

hpaulj
hpaulj

Reputation: 231375

The conflict_handler route:

In [5]: parser=argparse.ArgumentParser(conflict_handler='resolve')                             
In [6]: parser.add_argument('-h','--handle',help='handle foobar',default='foo');               

In [7]: parser.print_help()                                                                    
usage: ipython3 [--help] [-h HANDLE]

optional arguments:
  --help                show this help message and exit
  -h HANDLE, --handle HANDLE
                        handle foobar

resolve just changed the '-h', not the '--help'.

Using the new '-h':

In [8]: parser.parse_args('-h bar'.split())                                                    
Out[8]: Namespace(handle='bar')

Since abbreviations are still allowed '-help' with one dash gives unexpected results:

In [9]: parser.parse_args('-help'.split())                                                     
Out[9]: Namespace(handle='elp')

Correct help:

In [10]: parser.parse_args('--help'.split())                                                   
usage: ipython3 [--help] [-h HANDLE]

optional arguments:
  --help                show this help message and exit
  -h HANDLE, --handle HANDLE
                        handle foobar
An exception has occurred, use %tb to see the full traceback.

SystemExit: 0

/usr/local/lib/python3.6/dist-packages/IPython/core/interactiveshell.py:3327: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)

Look at the code for the _handle_conflict_resolve method to see exactly what it does.

Upvotes: 2

Related Questions