18

我正在使用 Argparse 编写一个命令行实用程序,并添加了一堆 sub_parsers(子命令)。在帮助菜单中,它们出现在名为“命令”的组下,我得到了所有可能选项的不错列表。然而,在此列表出现之前,所有相同的命令都出现在大括号中的组标题下,如下所示:

Commands:
    {foo, bar}

    foo          - foo does foo
    bar          - bar does bar

我想删除出现在大括号中的多余条目。它只出现在这个充满 sub_parsers 的组中。

我处理这个问题的代码如下所示:(其中 parser 是 ArgumentParser() 实例)

subparsers = parser.add_subparsers(title="Commands")

foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")

我查看了我的命令操作组的属性和方法,似乎找不到任何可以为我解决这个问题的东西(至少从我能理解的情况来看)。我不确定是否有其他人处理过这个问题,我意识到这可能有点晦涩难懂。再一次,我要做的就是找到删除出现在大括号中的命令的冗余列表的方法。

4

3 回答 3

15

“{foo,bar}”部分是参数“metavar”。元变量是 argparse 引用用法和帮助字符串中的预期参数值的方式。argparse 将子命令视为具有多个选项的参数,因此如果您不指定元变量,则默认值是花括号中的选项列表(子命令)。它让用户知道子命令的可能选项,但由于它们列在下面,它是多余的,如果你有很多子命令,它就很难看。

您可以轻松地用自己选择的元变量替换:

subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
于 2012-08-04T15:11:46.500 回答
4

在深入研究 argparse 源代码之后,我构建了一个hack来删除多余的{cmd1,...}选择列表。

hack 实现了一个自定义帮助格式化程序,它HelpFormatter在处理子解析器操作时修改了格式化方法。具体来说,它删除了子命令参数组中的子解析器metavarhelp行,并删除了这些子命令的额外缩进。

请小心使用

python 3版本,用python3.6测试

from argparse import ArgumentParser, HelpFormatter, _SubParsersAction

class NoSubparsersMetavarFormatter(HelpFormatter):

    def _format_action(self, action):
        result = super()._format_action(action)
        if isinstance(action, _SubParsersAction):
            # fix indentation on first line
            return "%*s%s" % (self._current_indent, "", result.lstrip())
        return result

    def _format_action_invocation(self, action):
        if isinstance(action, _SubParsersAction):
            # remove metavar and help line
            return ""
        return super()._format_action_invocation(action)

    def _iter_indented_subactions(self, action):
        if isinstance(action, _SubParsersAction):
            try:
                get_subactions = action._get_subactions
            except AttributeError:
                pass
            else:
                # remove indentation
                yield from get_subactions()
        else:
            yield from super()._iter_indented_subactions(action)

parser = ArgumentParser(formatter_class=NoSubparsersMetavarFormatter)
subparsers = parser.add_subparsers(title="Commands")

foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")

parser.parse_args(['-h'])

python 2版本,用python2.7测试

from argparse import ArgumentParser, HelpFormatter, _SubParsersAction

class NoSubparsersMetavarFormatter(HelpFormatter):

    def _format_action(self, action):
        result = super(NoSubparsersMetavarFormatter,
                       self)._format_action(action)
        if isinstance(action, _SubParsersAction):
            return "%*s%s" % (self._current_indent, "", result.lstrip())
        return result

    def _format_action_invocation(self, action):
        if isinstance(action, _SubParsersAction):
            return ""
        return super(NoSubparsersMetavarFormatter,
                     self)._format_action_invocation(action)

    def _iter_indented_subactions(self, action):
        if isinstance(action, _SubParsersAction):
            try:
                get_subactions = action._get_subactions
            except AttributeError:
                pass
            else:
                for subaction in get_subactions():
                    yield subaction
        else:
            for subaction in super(NoSubparsersMetavarFormatter,
                                   self)._iter_indented_subactions(action):
                yield subaction

parser = ArgumentParser(formatter_class=NoSubparsersMetavarFormatter)
subparsers = parser.add_subparsers(title="Commands")

foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")

parser.parse_args(['-h'])

样本输出:

usage: a.py [-h] {foo,bar} ...

optional arguments:
  -h, --help  show this help message and exit

Commands:
  foo         - foo does foo
  bar         - bar does bar
于 2018-01-01T16:15:02.210 回答
3

您可以通过编写自己的格式化程序类、基于argparse.HelpFormatter的接口并使用参数将其传递给解析器的构造函数来自定义帮助消息格式formatter_class

有关更多详细信息,请参阅http://docs.python.org/dev/library/argparse.html#formatter-class

于 2012-06-18T19:43:02.387 回答