In the argparse package the metavar parameter modifies the displayed help message of a program. The following program is not intended to work, it is simply used to demonstrate the behavior of the metavar parameter.
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "Print a range.")
    parser.add_argument("-range1", nargs = 3, type = int, help = "Specify range with: start, stop, step.", metavar = ("start", "stop", "step"))
    parser.add_argument("-range2", nargs = 3, type = int, help = "Specify range with: start, stop, step.", metavar = "r2")
The corresponding help message is:
usage: main.py [-h] [-range1 start stop step] [-range2 r2 r2 r2]
Print a range.
optional arguments:
  -h, --help            show this help message and exit
  -range1 start stop step
                        Specify range with: start, stop, step.
  -range2 r2 r2 r2      Specify range with: start, stop, step.
Please note the differences behind -range1 and -range2. Clearly -range1 is the preferred way of the help message.
Up to this point everything is clear to me. However, if I change the optional -range1 argument to a positional range1 argument, argparse cannot deal with the tuple of the metavar parameter (ValueError: too many values to unpack).
The only way I was able to get it work was in the way -range2 is done. But then the help message is by far not as good as for the -range1 case.
Is there a way to get the same help message as for the -range1 case but for a positional argument instead of an optional?
How about:
import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "Print a range.")
    parser.add_argument("start", type = int, help = "Specify start.", )
    parser.add_argument("stop", type = int, help = "Specify stop.", )
    parser.add_argument("step", type = int, help = "Specify step.", )
    args=parser.parse_args()
    print(args)
which yields
% test.py -h
usage: test.py [-h] start stop step
Print a range.
positional arguments:
  start       Specify start.
  stop        Specify stop.
  step        Specify step.
optional arguments:
  -h, --help  show this help message and exit
                        However, if I change the optional -range1 argument to a positional range1 argument, argparse cannot deal with the tuple of the metavar parameter (ValueError: too many values to unpack).
argparse shouldn't be giving that too many values to unpack error message.  It's produced by metavar, = self._metavar_formatter(action, default)(1).  Normally this function produces a single item list or tuple, but in your case it returns the tuple metavar.  It needs to give a more informative error message (tuple metavar not allowed with positionals ?), or gracefully adapt the metavar (start|stop|step ?).  Another option is to use the default metavar in the help line instead of the tuple.
The tuple metavar works ok on the usage line.
I think the help formatting was written with uniform positionals in mind.  On the usage line it might show X [X [X ...]], but on the help line just X ...   description of X.  
Your 3 items have distinct names, so unutbu's suggestion of 3 separate positionals is probably what the argparse designers had in mind.
This issue has been raised (but not patched)
http://bugs.python.org/issue14074 "argparse allows nargs>1 for positional arguments but doesn't allow metavar to be a tuple"
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