【问题标题】:Argparse python, remove subparser list in help menuArgparse python,在帮助菜单中删除子解析器列表
【发布时间】:2012-06-19 16:19:35
【问题描述】:

我正在使用 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")

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

【问题讨论】:

    标签: python argparse


    【解决方案1】:

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

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

    subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
    

    【讨论】:

    • 完美,正是我需要的!谢谢。
    • 仍然无法完全删除该标题。 argparse 留空行。
    • @anatolytechtonik 在下面查看我的 hack。
    【解决方案2】:

    在深入研究 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
    

    【讨论】:

    • 我做的有点相似 - techtonik.rainforce.org/2016/11/… - 我认为arparse 痛苦的正确方法是一步导出所有数据,然后只是格式化这些数据而不是调用很多黑客。
    【解决方案3】:

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

    更多详情见http://docs.python.org/dev/library/argparse.html#formatter-class

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-04
      • 2013-02-01
      • 2023-03-23
      • 2018-12-31
      • 2021-09-24
      • 2017-05-13
      • 2013-12-21
      • 2013-10-07
      相关资源
      最近更新 更多