New submission from Vasilis Vasaitis: The title says it all really, but to demostrate: Let's say I'm building a program which takes another command as its argument(s) on the command line, to execute it in a special way or whatever. The natural way to do this then would be something like the following:
import argparse parser = argparse.ArgumentParser() parser.add_argument('cmd', nargs='*') parser.parse_args() Which gives the following output with -h: usage: nargs.py [-h] [cmd [cmd ...]] positional arguments: cmd optional arguments: -h, --help show this help message and exit Now, let's say I want to have 'command' printed in the help output, but still write the shorter 'cmd' in the code. Naturally I would make use of the metavar feature: import argparse parser = argparse.ArgumentParser() parser.add_argument('cmd', nargs='*', metavar='command') parser.parse_args() So now the help output is: usage: nargs.py [-h] [command [command ...]] positional arguments: command optional arguments: -h, --help show this help message and exit That's better, but I don't really want it to say 'command' twice there, it's more like a command and then its arguments. So what about a tuple instead? import argparse parser = argparse.ArgumentParser() parser.add_argument('cmd', nargs='*', metavar=('command', 'arguments')) parser.parse_args() So let's see what happens now with -h: Traceback (most recent call last): File "/Users/Vasilis/Sources/Tests/nargs.py", line 6, in <module> parser.parse_args() File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1717, in parse_args args, argv = self.parse_known_args(args, namespace) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1749, in parse_known_args namespace, args = self._parse_known_args(args, namespace) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1955, in _parse_known_args start_index = consume_optional(start_index) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1895, in consume_optional take_action(action, args, option_string) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1823, in take_action action(self, namespace, argument_values, option_string) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1016, in __call__ parser.print_help() File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 2348, in print_help self._print_message(self.format_help(), file) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 2325, in format_help formatter.add_arguments(action_group._group_actions) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 272, in add_arguments self.add_argument(action) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 257, in add_argument invocations = [get_invocation(action)] File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 535, in _format_action_invocation metavar, = self._metavar_formatter(action, default)(1) ValueError: too many values to unpack (expected 1) Hm, that didn't go very well. Perhaps I can try with a single element in the tuple, as the exception seems to suggest: import argparse parser = argparse.ArgumentParser() parser.add_argument('cmd', nargs='*', metavar=('command',)) parser.parse_args() Any better? Traceback (most recent call last): File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1334, in add_argument self._get_formatter()._format_args(action, None) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 579, in _format_args result = '[%s [%s ...]]' % get_metavar(2) TypeError: not enough arguments for format string During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/Vasilis/Sources/Tests/nargs.py", line 5, in <module> parser.add_argument('cmd', nargs='*', metavar=('command',)) File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1336, in add_argument raise ValueError("length of metavar tuple does not match nargs") ValueError: length of metavar tuple does not match nargs No, not really. So there you have it. I think the two-element-tuple example should do the right thing (print "[command [arguments ...]]"). But if not, at least *some* kind of tuple should work without raising an exception. Apart from 3.4, I see precisely the same behaviour with Python 2.7 too. I haven't tested with any other version I'm afraid. ---------- components: Library (Lib) messages: 219429 nosy: vvas priority: normal severity: normal status: open title: argparse explodes with nargs='*' and a tuple metavar versions: Python 3.4 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue21616> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com