Argparse - Custom Action With No Argument?
For anyone who finds this in 2020: If you attempt to pass nargs=0 in the latest argparse package for python3, it will error with:
ValueError: nargs for store actions must be != 0; if you have nothing to store, actions such as store true or store const may be more appropriate
The solution you're probably looking for is to pass action="store_const" and const=True
Example:
parser = argparse.ArgumentParser
parser.add_argument('-s', '--start', help='Start script or whatever', action="store_const", const=True)
This will set the value for parser.start equal to "True" when the -s parameter is passed to main/the rest of the script.
As mgilson suggested nargs=0
does the trick. Since it's intrinsic to your action, I'd put it inside the action:
class StartAction(argparse.Action):
def __init__(self, nargs=0, **kw):
super().__init__(nargs=nargs, **kw)
def __call__(self, parser, namespace, values, option_string=None):
print "Hello"
start.add_argument('-s', '--start', action=StartAction)
And you have your desired behaviour without the redundancy of having to add nargs=0
to every add_argument()
call. Neat if you have multiple arguments working in the same way.
However users could still override the default of nargs=0
which is silly for your use case as demonstrated in the question. So I'd enforce it:
class StartAction(argparse.Action):
def __init__(self, nargs=0, **kw):
if nargs != 0:
raise ValueError('nargs for StartAction must be 0; it is '
'just a flag.')
super().__init__(nargs=nargs, **kw)
def __call__(self, parser, namespace, values, option_string=None):
print "Hello"
I wrote this example after consulting the above and trying out different methods. Here is a class which implements the "Uncount" acount, which is the opposite of the 'count' action.
import argparse
class Uncount(argparse.Action):
def __init__(self, option_strings, dest, nargs=0, choices=None, const=None, **kwargs):
if nargs != 0:
raise ValueError("no arguments to this parameter are allowed")
if const is not None:
raise ValueError("this parameter does not permit constants")
if choices is not None:
raise ValueError("no choices to this parameter are allowed")
super(Uncount, self).__init__(option_strings=option_strings, nargs=nargs, dest=dest,**kwargs)
def __call__(self, parser, namespace, values, option_string=None):
value = getattr(namespace, self.dest, 0)
setattr(namespace, self.dest, value-1)
opts={}
argparser = argparse.ArgumentParser(description='Report on other teams')
argparser.add_argument(
'-v','--verbose',dest='verbose',default=0,action='count',
help='increase log level',
)
argparser.add_argument(
'-q','--quiet',dest='verbose',default=0,action=Uncount,
help='increase log level',
)
Examples:
>>> argparser.parse_args('-q -q'.split())
Namespace(verbose=-2)
>>> argparser.parse_args('-q -v'.split())
Namespace(verbose=0)
>>> argparser.parse_args('-q -v -v'.split())
Namespace(verbose=1)
Try adding nargs=0
to your start.add_argument
:
start.add_argument('-s', '--start', action=StartAction, nargs=0)