I'm using the python package argparse, with simple configuration
When I try to add to my parser formatter_class=argparse.MetavarTypeHelpFormatter
I get error:
AttributeError: 'NoneType' object has no attribute '__name__'
did anyone else encounter that? and maybe know why?
this is my code:
import argparse
argParser = argparse.ArgumentParser(
formatter_class=argparse.MetavarTypeHelpFormatter)
argParser.add_argument(
"models",
default='',
nargs='+',
help="Which model(s) to execute")
args = argParser.parse_args()
print(args)
When I try it with out adding the formatter_class
it is working
It is also working with other formatter class like formatter_class=argparse.RawDescriptionHelpFormatter
I also tried it with prog
attribute and without
Short answer: the type
argument to add_argument
defaults to None
, not str
.
Less short answer: a type of None
behaves like a type of str
, but doesn't work with MetaVarTypeHelpFormatter
.
MetaVarTypeHelpFormatter
requires an explicit type for each argument.
argParser.add_argument(
"models",
default='',
nargs='+',
type=str,
help="Which model(s) to execute")
Its documented purpose is to use the name of the argument's type
attribute as the metavariable, and that attribute defaults to None
.
Although the default type of an argument is str
, that just means the str
value taken from the argument list is preserved if the argument's type
attribute is None
, or converted to the given type if it is not None
.
>>> p = argparse.ArgumentParser()
>>> print(p.add_argument("foo").type)
None
>>> print(p.add_argument("foo", type=int).type)
<class 'int'>
Each parser maintains a type registry, which means you can add your own arbitrary mappings of values to callables to produce types. For instance,
>>> import argparse
>>> p = argparse.ArgumentParser()
>>> p.register('type', 'lowercase', lambda x: x.lower())
>>> p.add_argument("foo", type='lowercase')
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type='lowercase', choices=None, required=True, help=None, metavar=None)
>>> p.parse_args(["HELLO WORLD"])
Namespace(foo='hello world')
Initially, the entry in the type registry maps None
to
def identity(string):
return string
which is why an argument with "type" None
otherwise behaves as if you had supplied str
explicitly.
The type registry isn't documented and, aside from this single entry, isn't used again, so it's not clear why it exists. The author may have had plans to use it more that never came to fruition. (Notice that each parser also has an action registry that gets used more often, which is why you can specify actions like 'append'
and 'store_const'
instead of specifying non-public classes like _AppendAction
and _StoreConstAction
directly.)