I'm writing a command-line utility using Argparse and have added a bunch of sub_parsers (sub commands). In the help menu they appear under a group called "commands" and I get a nice list of all the possible options. However before this list appears, all the same commands appear under the group title in braces like so:
Commands:
{foo, bar}
foo - foo does foo
bar - bar does bar
I want to remove the redundant entries which appear in braces. It only appears in this group which is filled with sub_parsers.
My code to handle this looks like so: (where parser is the ArgumentParser() instance)
subparsers = parser.add_subparsers(title="Commands")
foo = subparsers.add_parser("foo", help="- foo does foo")
bar = subparsers.add_parser("bar", help="- bar does bar")
I've looked at the attributes and methods of my commands action group and can't seem to find anything that will solve this for me (at least from what I can make sense of). I'm not sure if anyone else has dealt with this, I realize it's probably a bit obscure. And again, all I'm trying to do is find the way to remove the redundant list of the commands which appear in braces.
The "{foo,bar}" part is the argument 'metavar'. A metavar is how argparse refers to expected argument values in the usage and help strings. argparse treats subcommands like an argument with multiple choices so if you don't specify a metavar, the default is the list of choices (subcommands) in curly braces. It lets the user know the possible options for subcommands but since they're listed just below, it's redundant and if you have lots of subcommands, it's ugly.
You can easily replace with your own chosen metavar:
subparsers = parser.add_subparsers(title="Commands", metavar="<command>")
You can customize your help message formatting by writing your own formatter class, basing on argparse.HelpFormatter
's interface and passing it to parser's constructor using formatter_class
argument.
For more details see http://docs.python.org/dev/library/argparse.html#formatter-class
After diving really deep into argparse source code, I have constructed a hack to remove the redundant {cmd1,...}
choice list.
The hack implements a custom help formatter which modifies HelpFormatter
's formatting methods when dealing with subparsers action. Specifically, it removes subparsers metavar
and help
line in subcommand argument group, and removes extra indentation of those subcommands.
Please use with care .
The python 3 version, tested with 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'])
The python 2 version, tested with 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'])
Sample output:
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.