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