argparse中使用metavar和nargs='+'可以在帮助信息中获取编号参数吗?

8
argparse文档中,有一个使用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个回答

10

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 

一个位置参数没有选项字符串(或为空),因此它使用“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。看起来在使用、帮助信息和错误消息方面可能会出现问题。


实际上问题不在于使用,而在于格式化帮助行:

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

2
我会制作一个自定义的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'])

不幸的是,HelpFormatter没有公开的API,因此通过子类化和覆盖_format_args()方法很容易被未来的Python版本破坏。 - Graham501617

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接