假设我有以下argparse片段:

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的默认值,或者我应该子类化帮助格式化器?


当前回答

包装器类

这是我迄今为止发现的既可以显示默认值又可以使用其他格式化程序(如argparse)的最可靠的DRY方法。同时使用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文档字符串说:

此模块中的所有其他类都被视为实现细节。 (还要注意,HelpFormatter和RawDescriptionHelpFormatter只是 作为对象名被认为是公共的——格式化器对象的API是 仍然被认为是一个实现细节。)

参见:自定义argparse帮助消息

在Python 3.6.5上测试。

其他回答

在帮助输出中自动包含默认值通常是有用的,但只包含显式指定的值(使用default=..)。上面提到的方法在这方面有一些缺点:

ArgumentDefaultsHelpFormatter方法打印(默认值:None)每个没有显式指定默认值的参数,打印(默认值:False) 'flags' (action='store_true')。这会使帮助输出变得混乱。为了避免它,default=argparse。需要为每个这样的参数手动添加SUPPRESS。 '%(default)s'方法需要手动将其添加到我们希望打印在帮助中的所有参数的帮助字符串中。

这两种方法最终都需要手动干预来只打印“正确”的默认值。 一种自动实现的方法是增加ArgumentDefaultsHelpFormatter来忽略none和false的默认值:

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
                )

这将只打印帮助输出中显式设置的默认值。

注意:如果一个参数的默认值被显式地设置为None或False,它将不会在该类的帮助中显示;如果您希望在帮助输出中添加%(默认)s字符串来帮助该参数。

包装器类

这是我迄今为止发现的既可以显示默认值又可以使用其他格式化程序(如argparse)的最可靠的DRY方法。同时使用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文档字符串说:

此模块中的所有其他类都被视为实现细节。 (还要注意,HelpFormatter和RawDescriptionHelpFormatter只是 作为对象名被认为是公共的——格式化器对象的API是 仍然被认为是一个实现细节。)

参见:自定义argparse帮助消息

在Python 3.6.5上测试。

向帮助参数添加'%(默认)s'以控制显示内容。

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

注:

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

您可以参考printf文档了解更多详细信息。

使用argparse。ArgumentDefaultsHelpFormatter格式化程序:

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

引用文件:

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

注意,这只适用于定义了帮助文本的参数;如果参数没有帮助值,则没有帮助消息可以向其中添加有关默认值的信息。

扫描时间选项的准确输出然后变成:

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