Skip to content Skip to sidebar Skip to footer

Access "implicit" Metavar Value In Argument Help String

When you call add_argument on an argparse.ArgumentParser() without an explicit action, you get the 'store' action. In the auto-generated --help output you get the uppercase of the

Solution 1:

One thing you can do before calling parser.parse_args() is update those actions added to the parser that have a metavar attribute that is None:

for action in parser._actions:
    ifnothasattr(action, 'metavar') ornothasattr(action, 'dest'):
        continue
    metavar = getattr(action, 'metavar')
    if metavar isNone:
        action.metavar = action.dest.upper()

That generates output like:

  --version X.Y.Z  set version to X.Y.Z
  --dateDATE      use DATE instead of today

But as we say in the BDFL's native language: "mooi is anders" ¹


¹ beautiful looks different

Solution 2:

It's not going to be easy, at least not within argparse.

When you add_argument it creates an Action class object, and assigns attributes:

a1 = parser.add_argument('--version', metavar='X.Y.Z')
 a2 = parser.add_argument('--date')

a1.metavar will be 'X.Y.Z', a2.metavar will be the default None.

That's the value that is used in the help line, something like:

`'help %(metavar)`%{'metavar':action.metavar}'

That action.metavar attribute can be modified after creating the Action, as demonstrated in the other answer.

But for the usage and first part of help it does something like:

def_metavar_formatter(self, action, default_metavar):
        if action.metavar isnotNone:
            result = action.metavar
        elif action.choices isnotNone:
            choice_strs = [str(choice) for choice in action.choices]
            result = '{%s}' % ','.join(choice_strs)
        else:
            result = default_metavar
        ...

default_metavar is different for positionals and optionals, but basically is derived from action.dest. So the displayed metavar is generated on the fly, and not stored anywhere.


The %(metavar)s is handled in:

def _expand_help(self, action):
    params = dict(vars(action), prog=self._prog)
    for name inlist(params):
        ifparams[name] is SUPPRESS:
            del params[name]
    for name inlist(params):
        ifhasattr(params[name], '__name__'):
            params[name] = params[name].__name__
    ifparams.get('choices') isnot None:
        choices_str = ', '.join([str(c) for c inparams['choices']])
        params['choices'] = choices_str
    return self._get_help_string(action) % params

vars(action) makes a dictionary from all the attributes of the action.

I can imagine creating a Formatter subclass that modifies one or more of the methods. The existing subclasses work by modifying just one or two low level methods. But to do that requires studying the code.


In [329]: p = argparse.ArgumentParser()
In [330]: a1 = p.add_argument('--version', metavar='X.Y.Z')
In [331]: a1
Out[331]: _StoreAction(option_strings=['--version'], dest='version', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar='X.Y.Z')
In [332]: vars(a1)
Out[332]: 
{'option_strings': ['--version'],
 'dest': 'version',
 'nargs': None,
 'const': None,
 'default': None,
 'type': None,
 'choices': None,
 'required': False,
 'help': None,
 'metavar': 'X.Y.Z',
 'container': <argparse._ArgumentGroup at 0x7f72ecc4b4a8>}

A help with several parameters:

In [333]: a1.help='help %(metavar)s, %(dest)s, %(required)s'
In [334]: p.print_help()
usage: ipython3 [-h] [--version X.Y.Z]

optional arguments:
  -h, --help       show this help message and exit
  --version X.Y.Z  help X.Y.Z, version, False

Post a Comment for "Access "implicit" Metavar Value In Argument Help String"