Metavar: It provides a different name for optional argument in help messages. Provide a value for the metavar keyword argument within add_argument().
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', metavar='YYY')
>>> parser.add_argument('bar', metavar='XXX')
>>> parser.parse_args('X --foo Y'.split())
Namespace(bar='X', foo='Y')
>>> parser.print_help()
usage: [-h] [--foo YYY] XXX
positional arguments:
XXX
optional arguments:
-h, --help show this help message and exit
--foo YYY
Reference: http://www.usatlas.bnl.gov/~caballer/files/argparse/add_argument.html
Action: Arguments can trigger different actions, specified by the action argument to add_argument(). There are six built-in actions that can be triggered when an argument is encountered:
store: Save the value, after optionally converting it to a different type. This is the default action taken if none is specified explicitly.store_true/store_false: Save the appropriate boolean value.store_const: Save a value defined as part of the argument specification, rather than a value that comes from the arguments being parsed. This is typically used to implement command line flags that aren’t booleans.append: Save the value to a list. Multiple values are saved if the argument is repeated.append_const: Save a value defined in the argument specification to a list.version: Prints version details about the program and then exits.
Reference: http://bioportal.weizmann.ac.il/course/python/PyMOTW/PyMOTW/docs/argparse/index.html
Answer from subhadarshi samal on Stack OverflowMetavar: It provides a different name for optional argument in help messages. Provide a value for the metavar keyword argument within add_argument().
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', metavar='YYY')
>>> parser.add_argument('bar', metavar='XXX')
>>> parser.parse_args('X --foo Y'.split())
Namespace(bar='X', foo='Y')
>>> parser.print_help()
usage: [-h] [--foo YYY] XXX
positional arguments:
XXX
optional arguments:
-h, --help show this help message and exit
--foo YYY
Reference: http://www.usatlas.bnl.gov/~caballer/files/argparse/add_argument.html
Action: Arguments can trigger different actions, specified by the action argument to add_argument(). There are six built-in actions that can be triggered when an argument is encountered:
store: Save the value, after optionally converting it to a different type. This is the default action taken if none is specified explicitly.store_true/store_false: Save the appropriate boolean value.store_const: Save a value defined as part of the argument specification, rather than a value that comes from the arguments being parsed. This is typically used to implement command line flags that aren’t booleans.append: Save the value to a list. Multiple values are saved if the argument is repeated.append_const: Save a value defined in the argument specification to a list.version: Prints version details about the program and then exits.
Reference: http://bioportal.weizmann.ac.il/course/python/PyMOTW/PyMOTW/docs/argparse/index.html
metavar is used in help messages in a place of an expected argument. See FOO is a default metavar here:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar')
>>> parser.parse_args('X --foo Y'.split())
Namespace(bar='X', foo='Y')
>>> parser.print_help()
usage: [-h] [--foo FOO] bar
...
action defines how to handle command-line arguments: store it as a constant, append into a list, store a boolean value etc. There are several built-in actions available, plus it's easy to write a custom one.
Videos
I have just started learning Python, coming from more low level language's but have some shell scripting experiences.
I wanted to write a tool with command line arguments, and quickly found the argparse module in Python's documentation. I am prone to object oriented programming and quickly ended up in a situation with a mess of post-processing string arguments into different class instances.
My mediocre Google-Fu found multiple ways of cleanly support custom type parsing, namely using the add_argument's type or action parameters. However, no site really explained their purposes; just a bunch of examples, using either mechanism. I did not feel I got a good understanding from the docs either.
What is the purpose of these two mechanics?
I read somewhere that arguments are passed through the callable type parameter and then forwarded to the callable action parameter.
Is the type mechanism supposed to parse a string to another type, and action supposed to use that newly created type instance to do whatever magic you want to happen?
def make_action(additional_arg):
class customAction(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
print(additional_arg)
setattr(args, self.dest, values)
return customAction
#...
parser.add_argument('-e', '--example', action=make_action('your arg'))
Another solution is to derive the based class argparse.Action like this:
class CustomAction(argparse.Action):
def __init__(self,option_strings,
additional_arg1,additional_arg2,
dest=None,
nargs=0,
default=None,
required=False,
type=None,
metavar=None,
help=None):
self._a1=additional_arg1
self._a2=additional_arg2
super(CustomAction, self).__init__(
option_strings=option_strings,
dest=dest,
nargs=nargs,
default=default,
required=required,
metavar=metavar,
type=type,
help=help)
def __call__(self, parser, namespace, values, option_string=None):
print(self._a1)
print(self._a2)
setattr(namespace, self.dest, values)
#........
parser.add_argument('-e', '--example', action=CustomAction, additional_arg1='your arg', additional_arg2=42)
Alternatively, supply *args and **kwargs to pass through any additional parameters to the parent constructor.
class CustomAction(argparse.Action):
def __init__(self, option_strings, additional_arg1, additional_arg2,
*args, **kwargs):
self._a1 = additional_arg1
self._a2 = additional_arg2
super(CustomAction, self).__init__(option_strings=option_strings,
*args, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
print(self._a1)
print(self._a2)
setattr(namespace, self.dest, values)
#........
parser.add_argument('-e', '--example', action=CustomAction, additional_arg1='your arg', additional_arg2=42)
What about this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-k',metavar='n', dest='number', action='append', nargs='?', const=5)
args = parser.parse_args()
print(args.number[0])
'python3 test.py -k' outputs:
5
'python3 test.py -k=3' outputs:
3
An example using sys:
import sys
k = 5
for opt in sys.argv:
if opt.split('=')[0] == '-k':
if '=' in opt:
print(opt.split('=')[1])
if '=' not in opt:
print(k)
elif len(sys.argv) is 1:
print('No arguments were supplied')
It's a bit of a hack, but you could replace all equal signs in the arguments with spaces and then use argparse on them. This could work better if you want to still use argparse, e.g. for other arguments.
It would mean both -k=3 and -k 3 would work. Though also -k=3=-k=4=-k would be parsed without error.
Adapted from jmunsch's answer:
import argparse
import sys
# split all args with equal sign
args = []
for arg in sys.argv[1:]:
args.extend(arg.split('='))
# parse the args
parser = argparse.ArgumentParser()
parser.add_argument('-k', metavar='n', type=int, dest='number',
action='append', nargs='?', const=5)
args = parser.parse_args(args)
print(args.number[0])
This could be made more intelligent by only splitting args that start with '-k=':
# split all args with equal sign
args = []
for arg in sys.argv[1:]:
if arg[:2] == '-k=':
args.extend(arg.split('='))
else:
args.append(arg)