选项之前显示的 Argparse 子解析器帮助

Posted

技术标签:

【中文标题】选项之前显示的 Argparse 子解析器帮助【英文标题】:Argparse subparser help displayed before options 【发布时间】:2022-01-02 01:58:02 【问题描述】:

使用 argparse,目前我的 main.py --help 看起来像这样

usage: main.py [--options] <command>

options:
  -h, --help  show this help message and exit
  --debug     Logs extra information for debugging
  --version   show program's version number and exit
  --license   reads the GPLv3

commands:

    install   install packages
    remove    remove packages
    update    update package list and upgrade the system

有没有一种简单的方法可以让子解析器命令显示在全局选项之前?

目前我的配置有点长,但如果需要上下文我可以。我没有什么疯狂的事情,这是重要的事情。

formatter = lambda prog: argparse.RawDescriptionHelpFormatter(prog,
                                                max_help_position=64)
bin_name = Path(argv[0]).name
version = __version__
parser = nalaParser(    formatter_class=formatter,
                        usage=f'bin_name [--options] <command>', 
                        )

subparsers = parser.add_subparsers(title='commands', metavar='', dest='command')
parser._optionals.title = "options"

install_parser = subparsers.add_parser('install', help='install packages')
remove_parser = subparsers.add_parser('remove', help='remove packages')
update_parser = subparsers.add_parser('update', help='update package list and upgrade the system')

parser.add_argument('--debug', action='store_true', help='Logs extra information for debugging')
parser.add_argument('--version', action='version', version=f'bin_name version')
parser.add_argument('--license', action=GPLv3)

因为我已经在进行子类化,所以我只是在下面添加了这个方法到 nalaParser

def format_help(self):
    formatter = self._get_formatter()

    # usage
    formatter.add_usage(self.usage, self._actions,
                        self._mutually_exclusive_groups)

    # description
    formatter.add_text(self.description)

    index = -1
    # Put options last in the group
    for action_group in self._action_groups[:]:
        index = + 1
        if action_group.title == 'options':
            self._action_groups.append(self._action_groups.pop(index))

    # positionals, optionals and user-defined groups
    for action_group in self._action_groups:
        formatter.start_section(action_group.title)
        formatter.add_text(action_group.description)
        formatter.add_arguments(action_group._group_actions)
        formatter.end_section()


    # epilog
    formatter.add_text(self.epilog)

    # determine help from format above
    return formatter.format_help()

【问题讨论】:

查看format_help方法的代码。这就是设置格式化程序的原因,包括组。 【参考方案1】:

parser.format_help 按照创建顺序将action_groups 传递给格式化程序。

In [24]: parser._action_groups
Out[24]: 
[<argparse._ArgumentGroup at 0x7f8167ac02e0>,
 <argparse._ArgumentGroup at 0x7f8167ac0850>,
 <argparse._ArgumentGroup at 0x7f8167ac0490>]
In [25]: [a.title for a in parser._action_groups]
Out[25]: ['positional arguments', 'options', 'commands']

默认组为positionaloptionsadd_subparsers 将其 Action 放在 positional 组中,除非给定 title。在这种情况下,它会创建一个新组。

您可以调整 format_help 以重新排序它传递给格式化程序的组。

或者像使用可选参数一样更改“位置参数”标题可能会起作用(而不是给subparsers title 参数)。

无论如何,行为的关键在于这两种方法。

【讨论】:

我看这个东西太久了。我发誓,当您之前发表评论时,我上下查看了 format_help,但无法弄清楚。感谢您轻推我,我明白了。我覆盖了该方法,并且在 argparse 迭代 self._action_groups 之前,我对其进行了迭代,找到带有标题选项的方法并将其基本移至末尾。

以上是关于选项之前显示的 Argparse 子解析器帮助的主要内容,如果未能解决你的问题,请参考以下文章

Python Argparse 子解析器

Argparse - 子解析器中位置参数之前的可选参数

parser.add_argument()用法——命令行选项参数和子命令解析器

带有嵌套命名空间的 argparse 子命令

Python:正确处理子命令的全局选项的参数解析器

argparse:首先解析特定选项,同时在使用提示中显示所有选项