In the argparse document, there is an example using nargs='+'
:
parser.add_argument('integers', metavar='N', type=int, nargs='+')
The corresponding help information is
usage: prog.py [-h] [--sum] N [N ...]
Is it possible to set the metavar
such that the help info looks like this?
usage: prog.py [-h] [--sum] N1 [N2 ...]
Python argparse metavar The metavar option gives a name to the expected value in error and help outputs. The example names the expected value value . The default name is V . The given name is shown in the help output.
Using the nargs parameter in add_argument() , you can specify the number (or arbitrary number) of inputs the argument should expect. In this example named sum.py , the --value argument takes in 3 integers and will print the sum.
Metavar: It provides a different name for optional argument in help messages.
First, we need the argparse package, so we go ahead and import it on Line 2. On Line 5 we instantiate the ArgumentParser object as ap . Then on Lines 6 and 7 we add our only argument, --name . We must specify both shorthand ( -n ) and longhand versions ( --name ) where either flag could be used in the command line.
metavar
can be tuple, as in
In [26]: parser = argparse.ArgumentParser()
In [27]: a=parser.add_argument('--integers', metavar=('N1','N2'), type=int, nargs='+');
In [28]: parser.print_help()
usage: ipython3 [-h] [--integers N1 [N2 ...]]
optional arguments:
-h, --help show this help message and exit
--integers N1 [N2 ...]
But that only works for optionals (flagged arguments), not positionals. I'm not exactly sure why, though I may have dug into this issue before.
https://docs.python.org/3/library/argparse.html#metavar
With the positional, the error stack includes:
/usr/lib/python3.5/argparse.py in _format_action_invocation(self, action)
542 if not action.option_strings:
543 default = self._get_default_metavar_for_positional(action)
--> 544 metavar, = self._metavar_formatter(action, default)(1)
545 return metavar
546
A positional
doesn't have option_strings
(or its empty), so it's using the metavar, = ...
unpacking idiom to ask for just one string. Hence the error: ValueError: too many values to unpack (expected 1)
.
So expecting only one metavar
variable is quite intentional, but I'm not sure about the rational. Maybe it's because it would be harder to tell where one positional ends and the next starts in the usage
:
In [34]: parser = argparse.ArgumentParser()
In [35]: parser.add_argument('foo', type=int, nargs=2);
In [36]: parser.add_argument('bar', type=int, nargs='+');
In [38]: parser.print_usage()
usage: ipython3 [-h] foo foo bar [bar ...]
I looked at this a couple of years ago, https://bugs.python.org/issue14074. Looks like there can be problems with the usage
, help-lines and error message.
Actually the problem isn't in the usage
, it's in formatting the help lines:
In [39]: parser = argparse.ArgumentParser()
In [40]: a=parser.add_argument('integers', metavar=('N1','N2'), type=int, nargs='+')
In [41]: parser.print_usage()
usage: ipython3 [-h] N1 [N2 ...]
The normal help line for a positional just shows one symbol, not the N [N ...]
of the usage:
In [43]: parser.print_help()
usage: ipython3 [-h] N [N ...]
positional arguments:
N
I would make a custom HelpFormatter
and use that. Below is a quick hack.
from argparse import HelpFormatter, ZERO_OR_MORE, ONE_OR_MORE
class CustomHelpFormatter(HelpFormatter):
def _format_args(self, action, default_metavar):
get_metavar = self._metavar_formatter(action, default_metavar)
if action.nargs == ZERO_OR_MORE:
return '[%s1 [%s2 ...]]' % get_metavar(2)
elif action.nargs == ONE_OR_MORE:
return '%s1 [%s2 ...]' % get_metavar(2)
else:
return super()._format_args(action, default_metavar)
>>> parser = argparse.ArgumentParser(formatter_class=CustomHelpFormatter)
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+')
>>> parser.parse_args(['--help'])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With