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


307

假设我有以下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格式化程序的子类?


5
您可能对docopt感兴趣。我再也没有看过argparse。
Paulo Scardine 2012年

14
@PauloScardine-内置于该语言是argparse的主要好处。
jordanm 2012年

1
@PauloScardine:将非标准库放入我当前的项目中确实会很痛苦,但是我肯定喜欢docopt输出的外观。谢谢你的提示!
JS。

@JS。您说“将非标准库放入我当前的项目中确实会很痛苦”真的吗?pypi有很多非常有用的库。在我的上下文中,很容易引入非标准库。如果在您的上下文中遇到困难,那是可悲的。
guettli

3
@guettli:该项目用于商业嵌入式项目。您说对了,安装很容易。获得公司法律的批准是一场噩梦。
JS。

Answers:


446

使用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)

12
我可以控制仅具有显式参数的参数default=显示默认值吗?由于我不喜欢“默认值:无”文本。
ziyuang

14
您可以将设置defaultSUPPRESSdefault=argparse.SUPPRESS。请注意,在这种情况下,没有属性将被添加到命名空间的结果,如果省略该参数,请参阅default文档
马丁·皮特斯

4
请注意,您还需要为创建的每个子解析器指定此名称。
KomodoDave 2014年

1
然后创建一个新问题,包括一个最小的可重现示例来演示该问题。就像我说的,它适用于Python 2.7。
马丁·彼得

3
@David我遇到了同样的问题。在中添加help参数add_argument,它应该起作用。
PabloDíazOgni

190

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

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

9
我喜欢这个选项,因为我已经使用过format_class = argparse.RawTestHelpFormatter,并且不想跟OOP放屁。
mqsoh

23
不要忘记在格式化字符串中包含变量“ type”,例如,字符串“%(default)s”或数字“%(default)d”。
strongMA 2014年

1
我更喜欢这种解决方案,它简单得多,而且不必显式处理没有默认值的参数。
void.pointer

@mqsoh多重继承实际上只是有效,但不幸的是它不是公共API:stackoverflow.com/a/52025430/895245
Ciro Santilli郝海东冠状病六四事件法轮功

1
我之所以这样,是因为更改格式程序类会在各处添加一堆“((默认值:无)”),这会使帮助混乱。
6005

11

包装类

这是迄今为止我发现的最可靠,最干的方法,既可以显示默认值,也可以同时使用另一个格式化程序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方法。argparsedocstring说:

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

另请参阅:自定义argparse帮助消息

在Python 3.6.5上测试。


1
太好了!最后,同时打印格式化的docstring和默认参数。谢谢
西尔万
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.