I am using argparse's action to add various data to a class. I would like to use that action on the default value if that arg is not provided at the command line. Is this possible? Thanks!
The argparse module will automatically allow an option -h or --help that prints a usage string for all the registered options. By default, the type is str , the default value is None , the help string is empty, and metavar is the option in upper case without initial dashes.
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.
The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present.
argparse
does not use the action
when applying the default
. It just uses setattr
. It may use the type
if the default is a string. But you can invoke the action
directly.
Here I use a custom action class borrowed from the documentation. In the first parse_args
nothing happens. Then I create a new namespace
, and invoke the action on the default. Then I pass that namespace to parse_args
. To understand this, you many need to import it into an interactive shell, and examine the attributes of the namespace and action.
# sample custom action from docs
class FooAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
print('Setting: %r %r %r' % (namespace, values, option_string))
setattr(namespace, self.dest, 'action:'+values)
p = argparse.ArgumentParser()
a1 = p.add_argument('--foo', action=FooAction, default='default')
print 'action:',a1
print p.parse_args([])
ns = argparse.Namespace()
a1(p, ns, a1.default, 'no string') # call action
print p.parse_args([],ns)
print p.parse_args(['--foo','1'],ns)
which produces:
action: FooAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='default', type=None, choices=None, help=None, metavar=None)
Namespace(foo='default')
Setting: Namespace() 'default' 'no string'
Namespace(foo='action:default')
Setting: Namespace(foo='action:default') '1' '--foo'
Namespace(foo='action:1')
I tailored the output to highlight when the action is being used.
Here's a way of performing a special action on an argument that isn't given on the command line (or given with a value == to the default). It's a simplification of the class given in https://stackoverflow.com/a/24638908/901925.
class Parser1:
def __init__(self, desc):
self.parser = argparse.ArgumentParser(description=desc)
self.actions = []
def milestone(self, help_='milestone for latest release.', default=None):
action = self.parser.add_argument('-m', '--milestone', help=help_, default=default)
self.actions.append(action)
return self
def parse(self):
args = self.parser.parse_args()
for a in self.actions:
if getattr(args, a.dest) == a.default:
print 'Please specify', a.dest
values = raw_input('>')
setattr(args, a.dest, values)
return args
print Parser1('desc').milestone(default='PROMPT').parse()
The prompting is done after parse_args
. I don't see any reason to call parse_args
again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With