I am working with the argparse
library in python. At some time, I use an argument called param
that takes 2 args: a key and a value. The line of code I use is the following:
parser.add_argument("-p", "--param", nargs=2, action="append",
help="key and value for query",
type=str, metavar="key value"
)
What's wrong here is when I call the help, it displays like this:
optional arguments:
-h, --help show this help message and exit
-p key value key value, --param key value key value
key and value for query parameters
The name 'key value' is repeated twice. I tried with lists, and generators but the only way i found was creating a little class containing the different values and yielding them when ask to __str__
like this:
class Meta:
def __init__(self, iterable):
self.gene = itertools.cycle(iterable)
def __str__(self):
return self.gene.__next__()
and I call add_argument
like this:
parser.add_argument("-p", "--param", nargs=2, action="append",
help="key and value for query parameters",
type=str, metavar=Meta(["key", "value"])
)
And it displays correctly:
-p key value, --param key value
key and value for query parameters
But I find pretty ugly using a temporary class like Meta
, and I feel like there must be another (better) way of doing this. Am I doing it right ?
Multiple Input ArgumentsUsing 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.
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.
2. I would add this: store_true means if true was specified then set param value but otherwise leave it to None. If default was also specified then param is set to that value instead of leaving it to None.
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.
From scrolling the doc deeply, I've found my answer
Different values of nargs may cause the metavar to be used multiple times. Providing a tuple to metavar specifies a different display for each of the arguments:
indeed, this works perfectly fine:
parser.add_argument("-p", "--param", nargs=2, action="append",
help="key and value for query parameters",
type=str, metavar=("key", "value")
)
The metavar handler isn't particularly sophisticated, but does take advantage of the information that tuple
class provides.
It wasn't obvious as to why your class worked, so I dug into the code.
Metavar is handled in the Formatter class with:
def _metavar_formatter(self, action, default_metavar):
if action.metavar is not None:
result = action.metavar
elif action.choices is not None:
choice_strs = [str(choice) for choice in action.choices]
result = '{%s}' % ','.join(choice_strs)
else:
result = default_metavar
def format(tuple_size):
if isinstance(result, tuple):
return result
else:
return (result, ) * tuple_size
return format
and
def _format_args(self, action, default_metavar):
get_metavar = self._metavar_formatter(action, default_metavar)
....
else:
# for numeric nargs
formats = ['%s' for _ in range(action.nargs)]
result = ' '.join(formats) % get_metavar(action.nargs)
return result
So with your Meta
:
In [261]: x = Meta(['one', 'two'])
In [262]: x
Out[262]: <__main__.Meta at 0x7f36980f65c0>
In [263]: x = (x,)*2
In [264]: x
Out[264]: (<__main__.Meta at 0x7f36980f65c0>, <__main__.Meta at 0x7f36980f65c0>)
In [265]: '%s %s'%x
Out[265]: 'one two'
With the tuple metavar:
In [266]: '%s %s'%('one','two')
Out[266]: 'one two'
and with a single string
In [267]: '%s %s'%(('one two',)*2)
Out[267]: 'one two one two'
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