Argparse帮助,避免重复使用全部大写字母

29

我想以与默认选项-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脚本中的变量通常都是大写字母。我认为将大写字母的元变量与小写字母的关键字区分开来是合适的。 - SingleNegationElimination
1
@TokenMacGuy 考虑到惯例,我可以接受这样做,但是 UP case(即大写)重复了不必要的部分(-i INI, --ini INI)。我已经相应地更新了问题标题,因为重复更加令人烦恼。 - matt wilkie
作为用户,您应该有自由选择任何帮助信息的灵活性。就个人而言,我觉得大写版本很丑,更不用说重复了。即使您打破了 shell 约定,元变量也可以被区分出来,例如 git commit -h - Marius Retegan
2个回答

25

您可以自定义 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()

输出

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

你的解决方案解决了我回答中存在的使用问题。 - John
我已经接受这个作为我的当前项目的可行解决方案。鉴于TokenMacGuy在Q上的观察,剥离大写字母可能不是一个明智的选择,因为它违反了惯例,并且使得选项是否需要跟随字符串变得不清楚(例如,“--download-only”是完整的,而“--ini”可能需要跟随路径或文件名)。 - matt wilkie
如果我有一个巨大的参数列表,编写一个手动使用说明声明所有可选参数将使处理和编写变得更加困难。而且,如果将来需要删除一些参数并添加一些新参数,则自动生成的用法说明会比手动处理更好。那么,有没有其他方法可以解决这个问题,即在用法说明中具有元字符而不在解释它的部分中具有元字符? - Rakholiya Jenish
@RakholiyaJenish:你可以在StackOverflow上提出一个适当的独立问题,附上当前问题的链接,并解释它与现有问题的区别,就像你在评论中所做的那样。 - jfs
感谢@J.F.Sebastian,我提出了一个问题,但没有得到任何评论或答案。您能否尝试查看一下这个问题。http://stackoverflow.com/questions/30704631/changing-the-metavar-value-in-argparse-only-in-argument-listing-and-not-in-its-u - Rakholiya Jenish

6

据我所知,您有两个选择:

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()

或者您可以编写自定义的格式化类,我意识到第一种选项可能不是完美的解决方案,因为它会在用法行中去掉大写字母。如果这很重要,这里是argparse的源代码,从我所知道的来看,默认的格式化类无法完全满足您的要求。

编辑:

好吧,我按照其他格式化程序的方式为您构建了自己的格式化类...不确定我是否建议您在生产代码中使用它,因为它没有任何官方的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()

你需要覆盖 _get_default_metavar_for_optional 方法吗?在你提供的源代码中,这个方法是一样的。你这么做是为了确保即使 HelpFormatter 实现其他功能,也会使用大写字母吗?如果回答得好并提供源代码链接,我会点赞的。 - Cody Piersall
我加入了那个方法是为了更清晰明了。当我读到方法名_get_default_metavar_for_optional时,它并没有直接表达出str.upper的含义。而相比之下,我可以猜测_format_args可能会执行一些字符串格式化操作。 - John
“_get_default_metavar_for_optional” 怎么可能不让人想到 str.upper 呢?开个玩笑,当然啦;你说得有道理。 - Cody Piersall

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