Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize argparse help message

I have written the following sample code to demonstrate my issue.

import argparse  parser = argparse.ArgumentParser() parser.add_argument('-v', '--version', action='version',                     version='%(prog)s 1.0') parser.parse_args() 

This produces the following help message.

$ python foo.py --help usage: foo.py [-h] [-v]  optional arguments:   -h, --help     show this help message and exit   -v, --version  show program's version number and exit 

I want to customize this help output such that it capitalizes all phrases and sentences, and puts period after sentences. In other words, I want the help message to be generated like this.

$ python foo.py --help Usage: foo.py [-h] [-v]  Optional arguments:   -h, --help     Show this help message and exit.   -v, --version  Show program's version number and exit. 

Is this something that I can control using the argparse API. If so, how? Could you please provide a small example that shows how this can be done?

like image 366
Lone Learner Avatar asked Mar 07 '16 15:03

Lone Learner


People also ask

How do you add help in Argparse?

As before, argparse automatically creates a --help option and documents your command-line interface (including the --upper-case option you just added). Try invoking aquarium.py with the --help option again to receive the updated help text: python3 aquarium.py --help.

How do you add an optional argument in Argparse?

Optional Arguments To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.

What is action Store_true in Argparse?

The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present. The source for this behavior is succinct and clear: http://hg.python.org/cpython/file/2.7/Lib/argparse.py#l861.

What does Argparse ArgumentParser () do?

>>> parser = argparse.ArgumentParser(description='Process some integers.') The ArgumentParser object will hold all the information necessary to parse the command line into Python data types.


2 Answers

First of all: capitalising those phrases flies in the face of convention, and argparse isn't really tooled to help you change these strings easily. You have three different classes of strings here: boilerplate text from the help formatter, section titles, and help text per specific option. All these strings are localisable; you could just provide a 'capitalised' translation for all of these strings via the gettext() module support. That said, you can reach in and replace all these strings if you are determined enough and read the source code a little.

The version action includes a default help text, but you can supply your own by setting the help argument. The same applies to the help action; if you set the add_help argument to False you can add that action manually:

parser = argparse.ArgumentParser(add_help=False)  parser.add_argument('-v', '--version', action='version',                     version='%(prog)s 1.0', help="Show program's version number and exit.") parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,                     help='Show this help message and exit.') 

Next, the optional arguments message is a group title; each parser has two default groups, one for positional arguments, the other for optional. You can reach these by the attributes _positionals and _optionals, both of which have a title attribute:

parser._positionals.title = 'Positional arguments' parser._optionals.title = 'Optional arguments' 

Be warned, by accessing names starting with an underscore you are venturing into the undocumented private API of the module, and your code may break in future updates.

Finally, to change the usage string, you'll have to subclass the help formatter; pass the subclass in as the formatter_class argument:

class CapitalisedHelpFormatter(argparse.HelpFormatter):     def add_usage(self, usage, actions, groups, prefix=None):         if prefix is None:             prefix = 'Usage: '         return super(CapitalisedHelpFormatter, self).add_usage(             usage, actions, groups, prefix)  parser = argparse.ArgumentParser(formatter_class=CapitalisedHelpFormatter) 

Demo, putting these all together:

>>> import argparse >>> class CapitalisedHelpFormatter(argparse.HelpFormatter): ...     def add_usage(self, usage, actions, groups, prefix=None): ...         if prefix is None: ...             prefix = 'Usage: ' ...         return super(CapitalisedHelpFormatter, self).add_usage( ...             usage, actions, groups, prefix) ... >>> parser = argparse.ArgumentParser(add_help=False, formatter_class=CapitalisedHelpFormatter) >>> parser._positionals.title = 'Positional arguments' >>> parser._optionals.title = 'Optional arguments' >>> parser.add_argument('-v', '--version', action='version', ...                     version='%(prog)s 1.0', help="Show program's version number and exit.") _VersionAction(option_strings=['-v', '--version'], dest='version', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help="Show program's version number and exit.", metavar=None) >>> parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, ...                     help='Show this help message and exit.') _HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='Show this help message and exit.', metavar=None) >>> print(parser.format_help()) Usage: [-v] [-h]  Optional arguments:   -v, --version  Show program's version number and exit.   -h, --help     Show this help message and exit. 
like image 68
Martijn Pieters Avatar answered Sep 17 '22 14:09

Martijn Pieters


Martijn has give a couple of the fixes that came to mind - the providing the help parameter, and a custom Formatter class.

One other partial fix is to modify the help string after the argument is created. add_argument creates and returns an Action object that contains the parameters and defaults. You can save a link to this, and modify the Action. You can also get a list of those actions, and act on that.

Let me illustrate, for a simple parser with the default help and one other argument, the action list is:

In [1064]: parser._actions Out[1064]:  [_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None),  _StoreAction(option_strings=['-f', '--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)] 

I can view and modify the help attribute of any of these:

In [1065]: parser._actions[0].help Out[1065]: 'show this help message and exit' In [1066]: parser._actions[0].help='Show this help message and exit.' 

producing this help:

In [1067]: parser.parse_args(['-h']) usage: ipython3 [-h] [-f FOO]     optional arguments:   -h, --help         Show this help message and exit.   -f FOO, --foo FOO 

Using the parser._actions list uses a 'private' attribute, which some people consider unwise. But in Python that public/private distinction is not tight, and can be broken with care. Martijn is doing that by accessing the parser._positionals.title.

Another way to change that group title is with custom argument groups

ogroup=parser.add_argument_group('Correct Optionals Title') ogroup.add_argument('-v',...) ogroup.add_argument('-h',...) 
like image 35
hpaulj Avatar answered Sep 19 '22 14:09

hpaulj