帮助文本中的 Python argparse 参数顺序

Posted

技术标签:

【中文标题】帮助文本中的 Python argparse 参数顺序【英文标题】:Python argparse argument order in help text 【发布时间】:2020-10-12 13:53:59 【问题描述】:

我的 Python 程序使用 argparse 模块接受命令行参数,它按预期工作,但是,帮助文本有点误导,我想为使用我的程序的其他人修复它。

目前,我有一个位置参数,它是一个目录和一个可选参数-p,它使用add_argument 函数的nargs=+ 参数接受任意数量的包名称。 DIR 位置参数需要在可选参数列表之前指定,否则该目录将被错误地添加到包名称列表中,并且会出错说没有指定位置参数。帮助输出当前如下所示:

package_info.py --help
usage: package_info.py [-h] [-v] [--no-cache] [-g FILE] [-p [PKG [PKG ...]]]
                       DIR

Get information on packages in ros workspace.

positional arguments:
  DIR                   The directory containing rospackages.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Enables verbose mode
  --no-cache            Do not cache the dependency graph
  -g FILE, --graph-file FILE
                        The graph file to load from or save to.
  -p [PKG [PKG ...]], --packages [PKG [PKG ...]]
                        The packages to provide information on.

我希望它被格式化为在 -p 标志之前显示 DIR,以便用户更清楚地知道必须首先指定此参数,如下所示:

package_info.py --help
usage: package_info.py DIR [-h] [-v] [--no-cache] [-g FILE] [-p [PKG [PKG ...]]]
            .
            .
            .

package_info.py --help
usage: package_info.py DIR
                       [-h] [-v] [--no-cache] [-g FILE] [-p [PKG [PKG ...]]]
            .
            .
            .

是否有一种简单的方法来格式化帮助消息,或者我需要编写自定义帮助消息格式化程序吗?

【问题讨论】:

【参考方案1】:

您说的是usage 行。

使用格式化程序确实将positionals 分开并将它们放在最后,如果足够长的话,可能会放在它们自己的行上。是的,确实与处理“+”标记的参数有冲突。不应该,但是修复太复杂了,不能简单地插入。

我不建议更改使用格式化程序 - 这组方法太复杂(且脆弱)而无法轻松修补。

在定义ArgumentParser 时提供自定义usage 参数将是最简单的解决方法。我不记得它是如何与换行交互的。

【讨论】:

【参考方案2】:

查看answer provided by hpaulj 之后,我能够查看python3.5 的源代码,argparse 1.1 版,这是我系统上的版本,并找到了几行我可以修改以使其工作的代码。当然,这不是一个优雅的解决方案,而是灵活的(随着程序的发展,我不断添加/删除/修改命令行参数)并且可以快速实施。

我创建了一个继承自 argparse.HelpFormatter 类的自定义帮助格式化程序类。在我的自定义类中,我复制了_format_usage 函数并更改了以下几行:

# build full usage string
format = self._format_actions_usage
action_usage = format(optionals + positionals, groups)
usage = ' '.join([s for s in [prog, action_usage] if s])

# build full usage string
format = self._format_actions_usage
action_usage = format(positionals + optionals, groups)
usage = ' '.join([s for s in [prog, action_usage] if s])

如果不需要对文本进行换行,这将为我提供所需的格式。

我还更改了以下内容:

# if prog is short, follow it with optionals or positionals
if len(prefix) + len(prog) <= 0.75 * text_width:
    indent = ' ' * (len(prefix) + len(prog) + 1)
    if opt_parts:
        lines = get_lines([prog] + opt_parts, indent, prefix)
        lines.extend(get_lines(pos_parts, indent))
    elif pos_parts:
        lines = get_lines([prog] + pos_parts, indent, prefix)
    else:
        lines = [prog]

# if prog is short, follow it with optionals or positionals
if len(prefix) + len(prog) <= 0.75 * text_width:
    indent = ' ' * (len(prefix) + len(prog) + 1)
    if pos_parts:
        lines = get_lines([prog] + pos_parts, indent, prefix)
        lines.extend(get_lines(opt_parts, indent))
    elif opt_parts:
        lines = get_lines([prog] + opt_parts, indent, prefix)
    else:
        lines = [prog]

这为我提供了需要包装时所需的格式。

【讨论】:

以上是关于帮助文本中的 Python argparse 参数顺序的主要内容,如果未能解决你的问题,请参考以下文章

Python argparse:有没有办法控制帮助文本的空白? [复制]

Argparse:“可选参数”下列出的必需参数?

在没有任何参数的情况下调用脚本时使用 Python argparse 显示帮助消息

python命令行参数模块argparse

Python学习之Argparse 解析脚本参数详解

Python 处理脚本的命令行参数:使用argparse