我正在使用Argparse编写一个命令行实用程序,并添加了一堆sub_parsers(子命令)。 在帮助菜单中,它们出现在一个名为"命令"的组下,我得到了所有可能选项的漂亮列表。 但是,在此列表出现之前,所有相同的命令都显示在组标题下的大括号中,如下所示:
Commands:
{foo, bar}
foo - foo does foo
bar - bar does bar
我想删除出现在大括号中的冗余条目。 它只出现在这个充满sub_parsers的组中。
我处理这个问题的代码如下所示:(其中解析器是 ArgumentParser() 实例)
subparsers = parser.add_subparsers(title="Commands")
foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")
我已经查看了我的命令操作组的属性和方法,似乎找不到任何可以为我解决这个问题的东西(至少从我能理解的内容来看)。 我不确定是否有其他人处理过这个问题,我意识到这可能有点晦涩难懂。 再说一次,我要做的就是找到删除出现在大括号中的命令冗余列表的方法。
"{foo,bar}"部分是参数'metavar'。metavar 是 argparse 引用用法和帮助字符串中的预期参数值的方式。argparse 将子命令视为具有多个选择的参数,因此如果您不指定 metavar,则默认值为大括号中的选项(子命令)列表。它让用户知道子命令的可能选项,但由于它们列在下面,它是多余的,如果你有很多子命令,那就很难看了。
您可以轻松地替换为自己选择的metavar:
subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
在深入研究 argparse 源代码之后,我构建了一个技巧来删除多余的{cmd1,...}
选择列表。
该hack实现了一个自定义帮助格式化程序,该格式化程序在处理时修改了HelpFormatter
的格式化方法子解析器操作。具体来说,它删除了子解析器metavar
和 help
子命令参数组中的行,并删除多余的缩进这些子命令。
请小心使用。
python 3版本,使用python3.6进行测试
from argparse import ArgumentParser, HelpFormatter, _SubParsersAction
class NoSubparsersMetavarFormatter(HelpFormatter):
def _format_action(self, action):
result = super()._format_action(action)
if isinstance(action, _SubParsersAction):
# fix indentation on first line
return "%*s%s" % (self._current_indent, "", result.lstrip())
return result
def _format_action_invocation(self, action):
if isinstance(action, _SubParsersAction):
# remove metavar and help line
return ""
return super()._format_action_invocation(action)
def _iter_indented_subactions(self, action):
if isinstance(action, _SubParsersAction):
try:
get_subactions = action._get_subactions
except AttributeError:
pass
else:
# remove indentation
yield from get_subactions()
else:
yield from super()._iter_indented_subactions(action)
parser = ArgumentParser(formatter_class=NoSubparsersMetavarFormatter)
subparsers = parser.add_subparsers(title="Commands")
foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")
parser.parse_args(['-h'])
python 2版本,使用python2.7进行测试
from argparse import ArgumentParser, HelpFormatter, _SubParsersAction
class NoSubparsersMetavarFormatter(HelpFormatter):
def _format_action(self, action):
result = super(NoSubparsersMetavarFormatter,
self)._format_action(action)
if isinstance(action, _SubParsersAction):
return "%*s%s" % (self._current_indent, "", result.lstrip())
return result
def _format_action_invocation(self, action):
if isinstance(action, _SubParsersAction):
return ""
return super(NoSubparsersMetavarFormatter,
self)._format_action_invocation(action)
def _iter_indented_subactions(self, action):
if isinstance(action, _SubParsersAction):
try:
get_subactions = action._get_subactions
except AttributeError:
pass
else:
for subaction in get_subactions():
yield subaction
else:
for subaction in super(NoSubparsersMetavarFormatter,
self)._iter_indented_subactions(action):
yield subaction
parser = ArgumentParser(formatter_class=NoSubparsersMetavarFormatter)
subparsers = parser.add_subparsers(title="Commands")
foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")
parser.parse_args(['-h'])
示例输出:
usage: a.py [-h] {foo,bar} ...
optional arguments:
-h, --help show this help message and exit
Commands:
foo - foo does foo
bar - bar does bar
您可以通过编写自己的格式化程序类来自定义帮助消息格式,基于 argparse.HelpFormatter
的接口并使用formatter_class
参数将其传递给解析器的构造函数。
有关更多详细信息,请参阅 http://docs.python.org/dev/library/argparse.html#formatter-class