Argparse:在&#39中包含默认值的方法——help'?

假设我有以下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的默认值,或者我应该直接子类化help格式化器?

80622 次浏览

使用argparse.ArgumentDefaultsHelpFormatter格式化程序:

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

引用文档:

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

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

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

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

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

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

笔记:

  • 它是%+默认括号+格式字符(不要与花括号{default}混淆,我们在format或f-string中找到)
  • 别忘了加上“说明字符”。(例如,s表示字符串,d表示整数,f表示浮点数,等等)。
  • 您还可以添加常用的“打印”;格式说明符(比如浮点数、前导零的位数等)

你可以参考printf的文档获取更多细节。

包装器类

这是我迄今为止发现的最可靠的DRY方法,可以同时显示默认值和使用另一个格式化器,如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文档字符串说:

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

参见:自定义argparse帮助消息

在Python 3.6.5上测试。

能够在帮助输出中包含default值通常是有用的,但仅限于那些被显式地指定的值(使用default=..)。上面提到的方法在这方面有一些缺点:

  • ArgumentDefaultsHelpFormatter 方法为每个没有显式指定默认值的参数打印(default: None),为'flags' (action='store_true')打印(default: False)。这会使帮助输出变得混乱。为了避免这种情况,需要为每个这样的参数手动添加default=argparse.SUPPRESS

  • '%(default)s' 方法需要手动将其添加到所有参数的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 string到help参数。