Argparse:在“--help”中包含默认值的方法?

Posted

技术标签:

【中文标题】Argparse:在“--help”中包含默认值的方法?【英文标题】:Argparse: Way to include default values in '--help'? 【发布时间】:2012-08-22 11:47:48 【问题描述】:

假设我有以下 argparse sn-p:

diags.cmdln_parser.add_argument( '--scan-time',
                     action  = 'store',
                     nargs   = '?',
                     type    = int,
                     default = 5,
                     help    = "Wait SCAN-TIME seconds between status checks.")

目前,--help 返回:

usage: connection_check.py [-h]
                             [--version] [--scan-time [SCAN_TIME]]

          Test the reliability/uptime of a connection.



optional arguments:
-h, --help            show this help message and exit
--version             show program's version number and exit
--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.

我更喜欢这样的:

--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.
                    (Default = 5)

查看帮助格式化程序代码发现了有限的选项。有没有一种聪明的方法让argparse 以类似的方式打印--scan-time 的默认值,或者我应该只继承help 格式化程序?

【问题讨论】:

您可能对docopt 感兴趣。我再也没有看过 argparse。 @PauloScardine - 内置于语言中是 argparse 的一大优势。 @PauloScardine:将非标准库拉入我当前的项目确实会很痛苦,但我确实喜欢 docopt 输出的外观。感谢您的提示! @JS。您说“将非标准库拉入我当前的项目确实会很痛苦”真的吗? pypi 有很多非常有用的库。在我的上下文中,很容易引入非标准库。如果在您的上下文中很难,这很可悲。 @guettli:那个项目是针对商业嵌入式项目的。你是对的安装很容易。获得公司法务部门的批准是一场噩梦。 【参考方案1】:

使用argparse.ArgumentDefaultsHelpFormatter formatter:

parser = argparse.ArgumentParser(
    # ... other options ...
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

引用documentation:

另一个可用的格式化程序类ArgumentDefaultsHelpFormatter 将添加有关每个参数的默认值的信息。

请注意,这仅适用于定义了帮助文本的参数;如果参数没有help 值,则没有帮助消息添加有关默认值的信息。

您的扫描时间选项的确切输出将变为:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)

【讨论】:

我可以控制只有带有显式default= 的参数显示默认值吗?因为我不喜欢“默认:无”文本。 您可以将default设置为SUPPRESSdefault=argparse.SUPPRESS。请注意,在这种情况下,如果省略该参数,则不会将任何属性添加到命名空间结果中,请参阅the default documentation。 请注意,您还需要为每个创建的子解析器指定此项。 然后创建一个新问题,包括一个演示问题的minimal reproducible example。正如我所说,它适用于 Python 2.7。 @AzorAhai-him- 创建一个新类,将两者作为子类并将其用作格式化程序;例如class RawTextArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter, argparse.ArgumentDefaultsHelpFormatter): passparser = argparse.ArgumentParser(..., formatter_class=RawTextArgumentDefaultsHelpFormatter)。这两个变体覆盖了基本帮助格式化程序的两个不同方面,因此可以轻松组合。【参考方案2】:

'%(default)s'添加到帮助参数以控制显示的内容。

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")

注意事项

它是 %+ 默认括号 + 格式字符(不要与我们在 format 或 f-string 中找到的大括号 default 混淆) 不要忘记在末尾添加类型表示的“说明符字符”(例如,s 用于字符串,d 用于整数,f 用于浮点数等) 您还可以添加常用的“printf”格式说明符(如浮点数、前导零等)

您可以参考printf documentation了解更多详情。

【讨论】:

我喜欢这个选项,因为我已经使用了 format_class=argparse.RawTestHelpFormatter 并且不想在 OOP 上放屁。 不要忘记在格式化字符串中包含变量 'type' - 例如'%(default)s' 表示字符串,或 '%(default)d' 表示数字。 我更喜欢这个解决方案,它更简单,而且我不必显式处理没有默认值的参数。 @mqsoh 多重继承实际上只是工作,但不幸的是不是公共 API:***.com/a/52025430/895245 我喜欢这个,因为更改格式化程序类会在任何地方添加一堆“(默认值:无)”,这会使帮助变得混乱。【参考方案3】:

包装类

这是迄今为止我发现的最可靠和最简单的方法,既可以显示默认值,又可以同时使用其他格式化程序,例如 argparse.RawTextHelpFormatter

#!/usr/bin/env python3

import argparse

class ArgumentParserWithDefaults(argparse.ArgumentParser):
    def add_argument(self, *args, help=None, default=None, **kwargs):
        if help is not None:
            kwargs['help'] = help
        if default is not None and args[0] != '-h':
            kwargs['default'] = default
            if help is not None:
                kwargs['help'] += ' Default: '.format(default)
        super().add_argument(*args, **kwargs)

parser = ArgumentParserWithDefaults(
    formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)

parser.print_help()
print()
print(parser.parse_args())

输出:

usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
               [--no-help NO_HELP]

optional arguments:
  -h, --help            show this help message and exit
  -a A                  my help
                        for a Default: 13
  -b B                  my help
                        for b Default: 42
  --no-default NO_DEFAULT
                        my help
                        for no-default
  --no-help NO_HELP

Namespace(a=13, b=42, no_default=None, no_help=101)

ArgumentDefaultsHelpFormatter + RawTextHelpFormatter 多重继承

多重继承才行,但好像不是公共API:

#!/usr/bin/env python3

import argparse

class RawTextArgumentDefaultsHelpFormatter(
        argparse.ArgumentDefaultsHelpFormatter,
        argparse.RawTextHelpFormatter
    ):
        pass

parser = argparse.ArgumentParser(
    formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()

输出:

usage: a.py [-h] [-a A] [-b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A        my help
              for a (default: 13)
  -b B        my help
              for b (default: 42)

它可以正常工作,因为我们可以从https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 的来源中看到:

RawTextHelpFormatter 实现 _split_lines ArgumentDefaultsHelpFormatter 实现 _get_help_string

所以我们可以猜测它们会很好地协同工作。

但是,这似乎不是公共 API,formatter_class 的方法也不是,所以我认为目前没有公共 API 方法可以做到这一点。 argparse docstring 说:

此模块中的所有其他类都被视为实现细节。 (另请注意,HelpFormatter 和 RawDescriptionHelpFormatter 仅 被视为公共对象名称 - 格式化程序对象的 API 是 仍被视为实现细节。)

另见:Customize argparse help message

在 Python 3.6.5 上测试。

【讨论】:

太棒了!最后打印了格式化的文档字符串和默认参数。谢谢【参考方案4】:

能够自动在帮助输出中包含default值通常很有用,但仅限于那些明确指定的值(使用default=..) .已经提到的方法在这方面存在一些不足:

ArgumentDefaultsHelpFormattermethod 为未明确指定默认值的每个参数打印出(default: None),为“标志”(action='store_true') 打印出(default: False)。这会使帮助输出变得混乱。为避免这种情况,需要为每个此类参数手动添加default=argparse.SUPPRESS

'%(default)s' method 需要手动将其添加到我们确实希望在帮助中打印的所有参数的help 字符串中。

这两种方法最终都需要人工干预才能仅打印出“正确”的默认值。 一种自动执行此操作的方法是增加 ArgumentDefaultsHelpFormatter 以忽略 Nones 和 Falses 默认值:

class ExplicitDefaultsHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
    def _get_help_string(self, action):
        if action.default in (None, False):
            return action.help
        return super()._get_help_string(action)

用它代替ArgumentDefaultsHelpFormatter:

parser = argparse.ArgumentParser(
        formatter_class=ExplicitDefaultsHelpFormatter
                )

这将只打印帮助输出中明确设置的default 值。

注意:如果参数的默认值显式设置为NoneFalse,则不会在此类的帮助中显示;如果您希望在帮助输出中使用该参数,请将 %(default)s 字符串添加到 help

【讨论】:

以上是关于Argparse:在“--help”中包含默认值的方法?的主要内容,如果未能解决你的问题,请参考以下文章

仅显示特定行中包含特定值的行

PHP计算在许多列中包含相同值的MYSQL行

在数据框的选定列中包含 NA(缺失)值的行子集

如何在 FieldArray 中包含不同值的数组的 yup 验证中添加错误消息?

Access 2010:根据特定组合框条件过滤字段中包含多个值的报表

删除熊猫数据框中包含特定值的列和行[重复]