在 argparse 中自定义组间帮助
Customize help among groups in 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不适合我的情况,因为我一直在解析它,我只需要自定义帮助就可以显示。
我反对你正在尝试做的事情。
You are solving a problem that isn't yours to solve. return 使用信息是您脚本的工作。如果文本很多,这不是您的问题。你能做的事情,你正在做:将参数放入对用户有意义的组中。但是文字量不是数据结构的问题,而是数据表现的问题。
其次,您将遵循 没有人使用的惯例。通常有
man command
command --help
command subcommand --help
其他任何东西都会让初次使用的用户感到困惑。
此外,如果您有很多参数组,人们总是需要咨询 --help
以找出他们接下来必须咨询哪个 --help_*
。 当您可以立即在 --help
中展示它时,这可能会让用户感到沮丧。
如果您使用多个帮助页面,您将防止重复使用您的帮助文本。搜索,例如:如果不手动切换,则无法搜索多个页面。
正确的做法 是通过像 less
这样的分页器传递文本。这允许用户逐页阅读文本、搜索(按 /
)或将其保存到文件:
command --help | less
为了方便一些命令,比如git log
,甚至检查output is an interactive terminal and automatically 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()
这是自定义 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
subclass.
中的默认方法
我们还可以创建一个自定义 Help
操作 class,其行为类似于标准帮助,只是它需要某种 group_list 参数。但是这个 post-解析操作更易于编码和测试。
我正在使用 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不适合我的情况,因为我一直在解析它,我只需要自定义帮助就可以显示。
我反对你正在尝试做的事情。
You are solving a problem that isn't yours to solve. return 使用信息是您脚本的工作。如果文本很多,这不是您的问题。你能做的事情,你正在做:将参数放入对用户有意义的组中。但是文字量不是数据结构的问题,而是数据表现的问题。
其次,您将遵循 没有人使用的惯例。通常有
man command
command --help
command subcommand --help
其他任何东西都会让初次使用的用户感到困惑。
此外,如果您有很多参数组,人们总是需要咨询 --help
以找出他们接下来必须咨询哪个 --help_*
。 当您可以立即在 --help
中展示它时,这可能会让用户感到沮丧。
如果您使用多个帮助页面,您将防止重复使用您的帮助文本。搜索,例如:如果不手动切换,则无法搜索多个页面。
正确的做法 是通过像 less
这样的分页器传递文本。这允许用户逐页阅读文本、搜索(按 /
)或将其保存到文件:
command --help | less
为了方便一些命令,比如git log
,甚至检查output is an interactive terminal and automatically 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()
这是自定义 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
subclass.
我们还可以创建一个自定义 Help
操作 class,其行为类似于标准帮助,只是它需要某种 group_list 参数。但是这个 post-解析操作更易于编码和测试。