args的argparse metavar =' +'在帮助信息中获取编号参数?

时间:2018-01-24 18:24:11

标签: python argparse

argparse document中,有一个使用nargs='+'的示例:

parser.add_argument('integers', metavar='N', type=int, nargs='+')

相应的帮助信息是

usage: prog.py [-h] [--sum] N [N ...]

是否可以设置metavar以使帮助信息看起来像这样?

usage: prog.py [-h] [--sum] N1 [N2 ...]

2 个答案:

答案 0 :(得分:4)

metavar可以是元组,如

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 ...]

但这仅适用于选项(标记参数),而不适用于位置。我不确定为什么,虽然我之前可能已经深入研究过这个问题。

https://docs.python.org/3/library/argparse.html#metavar

对于位置,错误堆栈包括:

/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 

positional没有option_strings(或者为空),所以它使用metavar, = ...解包惯用法只要求一个字符串。因此错误:ValueError: too many values to unpack (expected 1)

所以期待只有一个metavar变量是非常有意的,但我不确定理性。也许是因为在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 ...]

几年前我看过这个,https://bugs.python.org/issue14074。看起来usage,帮助热线和错误消息可能存在问题。

实际上usage中的问题不在于格式化帮助热线:

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 ...]

位置的常规帮助行只显示一个符号,而不是用法的N [N ...]

In [43]: parser.print_help()
usage: ipython3 [-h] N [N ...]

positional arguments:
  N

答案 1 :(得分:1)

我会制作一个自定义HelpFormatter并使用它。下面是一个快速黑客。

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'])