Reputation: 16097
Suppose I have the following argparse snippet:
diags.cmdln_parser.add_argument( '--scan-time',
action = 'store',
nargs = '?',
type = int,
default = 5,
help = "Wait SCAN-TIME seconds between status checks.")
Currently, --help
returns:
usage: connection_check.py [-h]
[--version] [--scan-time [SCAN_TIME]]
Test the reliability/uptime of a connection.
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--scan-time [SCAN_TIME]
Wait SCAN-TIME seconds between status checks.
I would prefer something like:
--scan-time [SCAN_TIME]
Wait SCAN-TIME seconds between status checks.
(Default = 5)
Peeking at the help formatter code revealed limited options. Is there a clever way to get argparse
to print the default value for --scan-time
in a similar fashion, or should I just subclass the help
formatter?
Upvotes: 487
Views: 107623
Reputation: 105
It is often useful to be able to automatically include the default
values in the help output, but only those that were explicitly specified (with default=..
). The methods already mentioned have some shortcomings in this respect:
The ArgumentDefaultsHelpFormatter
method prints out (default: None)
for every argument whose default was not explicitly specified, and (default: False)
for 'flags' (action='store_true'
). This clutters the help output. To avoid it, default=argparse.SUPPRESS
needs to be manually added for each such argument.
The '%(default)s'
method requires manually adding it to all the arguments' help
strings that we do want printed in help.
Both methods end up needing manual intervention to print out only the "right" defaults.
One way to do this automatically is to augment the ArgumentDefaultsHelpFormatter
to ignore the None
s and False
s default values:
class ExplicitDefaultsHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
def _get_help_string(self, action):
if action.default is None or action.default is False:
return action.help
return super()._get_help_string(action)
Use it in place of ArgumentDefaultsHelpFormatter
:
parser = argparse.ArgumentParser(
formatter_class=ExplicitDefaultsHelpFormatter
)
This will print only the explicitly set default
values in the help output.
Note: if an argument's default was explicitly set as None
or False
, it won't be shown in help with this class; add %(default)s
string to help
for that argument if you want it in the help output.
Upvotes: 10
Reputation: 382850
Wrapper class
This is the most reliable and DRY approach I've found so far to both show defaults and use another formatter such as argparse.RawTextHelpFormatter
at the same time:
#!/usr/bin/env python3
import argparse
class ArgumentParserWithDefaults(argparse.ArgumentParser):
def add_argument(self, *args, help=None, default=None, **kwargs):
if help is not None:
kwargs['help'] = help
if default is not None and args[0] != '-h':
kwargs['default'] = default
if help is not None:
kwargs['help'] += ' Default: {}'.format(default)
super().add_argument(*args, **kwargs)
parser = ArgumentParserWithDefaults(
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)
parser.print_help()
print()
print(parser.parse_args())
Output:
usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
[--no-help NO_HELP]
optional arguments:
-h, --help show this help message and exit
-a A my help
for a Default: 13
-b B my help
for b Default: 42
--no-default NO_DEFAULT
my help
for no-default
--no-help NO_HELP
Namespace(a=13, b=42, no_default=None, no_help=101)
ArgumentDefaultsHelpFormatter
+ RawTextHelpFormatter
multiple inheritance
Multiple inheritance just works, but it does not seem to be public API:
#!/usr/bin/env python3
import argparse
class RawTextArgumentDefaultsHelpFormatter(
argparse.ArgumentDefaultsHelpFormatter,
argparse.RawTextHelpFormatter
):
pass
parser = argparse.ArgumentParser(
formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()
Output:
usage: a.py [-h] [-a A] [-b B]
optional arguments:
-h, --help show this help message and exit
-a A my help
for a (default: 13)
-b B my help
for b (default: 42)
It just works works because as we can see trivially from the sources https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 that:
RawTextHelpFormatter
implements _split_lines
ArgumentDefaultsHelpFormatter
implements _get_help_string
so we can guess that they will work together just fine.
However, this does not seem to be public API, and neither are the methods of formatter_class
, so I don't think there is a public API way to do it currently. argparse
docstring says:
All other classes in this module are considered implementation details. (Also note that HelpFormatter and RawDescriptionHelpFormatter are only considered public as object names -- the API of the formatter objects is still considered an implementation detail.)
See also: Customize argparse help message
Tested on Python 3.6.5.
Upvotes: 23
Reputation: 1121924
Use the argparse.ArgumentDefaultsHelpFormatter
formatter:
parser = argparse.ArgumentParser(
# ... other options ...
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
To quote the documentation:
The other formatter class available,
ArgumentDefaultsHelpFormatter
, will add information about the default value of each of the arguments.
Note that this only applies to arguments that have help text defined; with no help
value for an argument, there is no help message to add information about the default value to.
The exact output for your scan-time option then becomes:
--scan-time [SCAN_TIME]
Wait SCAN-TIME seconds between status checks.
(default: 5)
Upvotes: 708
Reputation: 3195
Add '%(default)s'
to the help parameter to control what is displayed.
parser.add_argument("--type", default="toto", choices=["toto","titi"],
help = "type (default: %(default)s)")
Notes:
%
+ default in parenthesis + format characters (not to be confused with curly brackets {default}
we find in format
or f-string)s
for strings, d
for integers, f
for floats, etc.)You can refer to printf documentation for more details.
Upvotes: 317