在argparse中的组之间自定义帮助

时间:2016-11-21 11:01:51

标签: python argparse

我正在使用 argparse ,我有各种各样的组,它们都有自己的选项。

现在使用 - help 选项,我不希望默认显示所有选项。只为--help显示一组组选项。

其他群组选项应根据其他帮助选项显示,--help_1--help_2

例如:

--help' to show Group 2 and 3
--help_1' to show Group 11 and 12
--help_2' to show Group 22 and 23

我知道我们可以使用 add_help = False 禁用默认的--help选项,但是如何才能仅显示选定的组特定帮助。

我们可以使用 _action_groups 属性从解析器中获取组列表,但它们不会公开任何 print_help()选项。

我的示例代码:

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('--help_a', action='store_true')
parser.add_argument('--help_b', action='store_true')

group1 = parser.add_argument_group("Feature 1")
group1.add_argument('--foo1')
group2 = parser.add_argument_group("Feature 2")
group2.add_argument('--foo2')
group3 = parser.add_argument_group("Feature 3")
group3.add_argument('--foo3')

# TODO: --help_a to only print "Feature 1" groups help
# and --help_b to print Feature 2 and 3's help.

编辑:使用subparser并添加解析器(而非群组)将解决上述问题。但是subparser不适合我的情况,因为我总是在解析它,我只需要自定义帮助来显示。

2 个答案:

答案 0 :(得分:1)

以下是自定义format_help方法:

import argparse

def format_help(self, groups=None):
    # self == parser
    formatter = self._get_formatter()

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

    # description
    formatter.add_text(self.description)

    if groups is None:
        groups = self._action_groups

    # positionals, optionals and user-defined groups
    for action_group in 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()

<your parser>

args = parser.parse_args()
# _action_groups[:2] are the default ones
if args.help_a:
    print(format_help(parser, [parser._action_groups[2]]))
    parser.exit()
if args.help_b:
    print(format_help(parser, parser._action_groups[3:]))
    parser.exit()

样品运行

1444:~/mypy$ python stack40718566.py --help_a
usage: stack40718566.py [-h] [--help_a] [--help_b] [--foo1 FOO1] [--foo2 FOO2]
                        [--foo3 FOO3]

Feature 1:
  --foo1 FOO1

1444:~/mypy$ python stack40718566.py --help_b
usage: stack40718566.py [-h] [--help_a] [--help_b] [--foo1 FOO1] [--foo2 FOO2]
                        [--foo3 FOO3]

Feature 2:
  --foo2 FOO2

Feature 3:
  --foo3 FOO3

所以它就像默认的format_help,除了它需要一个groups参数。它甚至可以替换ArgumentParser子类中的默认方法。

我们还可以创建一个自定义Help Action类,其行为与标准帮助类似,只是它需要某种group_list参数。但是这种解析后的动作更容易编码和测试。

答案 1 :(得分:0)

我建议你反对你想要做的事情。

You are solving a problem that isn't yours to solve.您的脚本的工作是返回使用信息。如果这是很多文字,那不是你的问题。您可以做的事情,您正在做的事情:将参数放入对用户有意义的组中。但是文本的数量不是数据结构的问题,而是数据表示的问题

其次,您将遵循惯例,没有人正在使用。通常有

man command
command --help
command subcommand --help

其他任何东西都会让初次使用者感到困惑。

此外,如果你有很多论据组,那么一个人总是需要咨询--help以找出他们接下来要咨询的--help_*当您可以立即在--help中展示时,这对用户来说可能会令人沮丧

如果您使用多个帮助页面,则会阻止重复使用帮助文字。搜索,例如:如果不手动切换,则无法搜索多个页面。

正确的方法是通过像less这样的分页器传递文本。这允许用户逐页阅读文本,搜索文本(按/)或将其保存到文件:

command --help | less

为方便起见,某些命令(例如git log)甚至会检查output is an interactive terminalautomatically pass the output through less。这意味着

command --help > help.txt

将帮助保存到文件,而

command --help

显示分页中的帮助文本,并可搜索。

所以我在Windows和UNIX上的建议是

import os
import sys
import argparse
import subprocess


def less(data):
    if sys.stdout.isatty():
        if os.name == 'posix':
            cmd = "less"
        elif os.name == 'nt':
            cmd = "more" 

        process = subprocess.Popen([cmd], stdin=subprocess.PIPE)

        try:
            process.stdin.write(data)
            process.communicate()
        except IOError:
            pass
    else:
        print data


class MyArgumentParser(argparse.ArgumentParser):
    def print_help(self, file=None):
        less(self.format_help())
        self.exit()


parser = MyArgumentParser(prog='PROG')
group1 = parser.add_argument_group("Feature 1")
group1.add_argument('--foo1')
group2 = parser.add_argument_group("Feature 2")
group2.add_argument('--foo2')
group3 = parser.add_argument_group("Feature 3")
group3.add_argument('--foo3')
# parse some argument lists
print parser.parse_args()