【问题标题】:argparse help without duplicate ALLCAPS没有重复 ALLCAPS 的 argparse 帮助
【发布时间】:2012-07-04 04:52:47
【问题描述】:

我想以与默认 -h--help-v--version 相同的方式显示我的选项的 argparse 帮助,选项后没有大写文本,或者至少没有重复的文本大写字母。

import argparse
p = argparse.ArgumentParser("a foo bar dustup")
p.add_argument('-i', '--ini', help="use alternate ini file")
print '\n', p.parse_args()

这是我目前通过python foobar.py -h 得到的:

usage: a foo bar dustup [-h] [-i INI]

optional arguments:
  -h, --help            show this help message and exit
  -i INI, --ini INI     use alternate ini

这就是我想要的:

usage: a foo bar dustup [-h] [-i INI]

optional arguments:
  -h, --help            show this help message and exit
  -i, --ini INI         use alternate ini

这也是可以接受的:

  -i, --ini             use alternate ini

我使用的是 python 2.7。

【问题讨论】:

  • 我认为我不同意这个问题的前提。命令行参数通常是从 shell 传递的,按照惯例,shell 脚本中的变量通常都是大写的。我认为区分大写的元变量和小写的关键字是合适的。
  • @TokenMacGuy 考虑到这个约定,我会接受它,除了不必要地重复 UP 案例(-i INI, --ini INI)。我已经相应地更新了 Q 标题,因为它是更令人烦恼的重复。
  • @TokenMacGuy 作为用户,您应该可以灵活地使用任何您认为合适的帮助信息。我个人觉得 CAPS 版本很难看,更不用说重复了。即使你打破了 shell 约定,也可以区分元变量,例如git commit -h

标签: python argparse


【解决方案1】:

您可以自定义usage 并将metavar 分配给一个空字符串:

import argparse

p = argparse.ArgumentParser("a foo bar dustup", usage='%(prog)s [-h] [-i INI]')
p.add_argument('-i', '--ini', help="use alternate ini file", metavar='')
p.print_help()

输出

用法: foo bardustup [-h] [-i INI] 可选参数: -h, --help 显示此帮助信息并退出 -i , --ini 使用备用 ini 文件

【讨论】:

  • +1 您的解决方案解决了我的回答遇到的使用问题。
  • 我已经接受了这个作为我当前项目的可行解决方案。鉴于 TokenMacGuy 对 Q 的观察,剥离 CAPS 可能不适合在任何地方使用,因为它违反了约定,并且不清楚选项是否需要后续字符串(例如,--download-only 是完整的,而 --ini 可能需要跟随路径或文件名)。
  • 如果我有一大堆论据怎么办。编写一份手动使用声明,说明我拥有的所有可选参数,这将使其更难处理和编写。同样在将来,如果要删除一些参数并且要添加一些新参数,那么我认为自动生成而不是手动处理使用语句会很好。那么有没有其他方法可以解决这个问题,而不是在使用语句中而不是在解释它的部分中。
  • @RakholiyaJenish:你可以问一个适当的单独 * 问题:用墨水写到当前问题,并解释它到底有什么不同——就像你在评论中所做的那样。
  • 感谢@J.F.Sebastian,我问了一个问题,但没有得到任何 cmets 或答案。请你试着看看它。 *.com/questions/30704631/…
【解决方案2】:

我可以告诉你有两个选择,

import argparse

p = argparse.ArgumentParser(description="a foo bar dustup")
p.add_argument('-i', '--ini', metavar='', help="use alternate ini file")

print '\n', p.parse_args()

或者您可以编写自定义formatter class,我意识到第一个选项可能不是一个完美的解决方案,因为它摆脱了使用行中的 CAPS。如果这很重要,那就是 argparse 的 source,据我所知,默认的格式化程序类不会完全按照您的意愿行事。

编辑:

好吧,我继续为您构建了您自己的格式化程序类,以与其他人相同的方式...不确定我是否建议您在生产代码中使用它,因为不会有任何官方 python 文档= P

import argparse
from argparse import HelpFormatter

class MyFormatter(HelpFormatter):
    """
        for matt wilkie on SO
    """

    def _format_action_invocation(self, action):
        if not action.option_strings:
            default = self._get_default_metavar_for_positional(action)
            metavar, = self._metavar_formatter(action, default)(1)
            return metavar

        else:
            parts = []

            # if the Optional doesn't take a value, format is:
            #    -s, --long
            if action.nargs == 0:
                parts.extend(action.option_strings)

            # if the Optional takes a value, format is:
            #    -s ARGS, --long ARGS
            else:
                default = self._get_default_metavar_for_optional(action)
                args_string = self._format_args(action, default)
                for option_string in action.option_strings:
                    parts.append(option_string)

                return '%s %s' % (', '.join(parts), args_string)

            return ', '.join(parts)

    def _get_default_metavar_for_optional(self, action):
        return action.dest.upper()

p = argparse.ArgumentParser("a foo bar dustup", formatter_class=MyFormatter)
p.add_argument('-i', '--ini', help="use alternate ini file")
p.print_help()

【讨论】:

  • +1 以获得很好的答案和源代码链接。您是否需要覆盖_get_default_metavar_for_optional 方法?在您链接到它的源代码中是相同的方法。您是否这样做是为了确保即使 HelpFormatter 稍后实现其他内容也使用大写?
  • 为了清楚起见,我包含了该方法,当我阅读方法名称 _get_default_metavar_for_optional 时,它并没有完全对我尖叫 str.upper。我可以猜到_format_args 可能会进行一些字符串格式化。
  • _get_default_metavar_for_optional not 怎么尖叫str.upper?开个玩笑,当然;你说得很好。