Argparse default parameter based on another option

Suppose I have a argparse script:

import argparse parser = argparse.ArgumentParser() parser.add_argument("--foo", required=True) 

Now I want to add another parameter --bar, which by default will add "_BAR" to what was specified with the -foo argument.

My goal:

 >>> parser.parse_args(['--foo', 'FOO']) >>> Namespace(foo='FOO', bar="FOO_BAR") 

and

 >>> parser.parse_args(['--foo', 'FOO', '--bar', 'BAR']) >>> Namespace(foo='FOO', bar="BAR") 

I need something like this:

 parser.add_argument("--bar", default=get_optional_foo + "_BAR") 
+7
default argparse
source share
2 answers

Here is another attempt to write a custom Action class

 import argparse class FooAction(argparse.Action): # adapted from documentation def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values) defaultbar = getattr(namespace, 'bar') try: defaultbar = defaultbar%values except TypeError: # BAR has already been replaced pass setattr(namespace, 'bar', defaultbar) parser = argparse.ArgumentParser() parser.add_argument("--foo", required=True, action=FooAction) parser.add_argument("--bar", default="%s_BAR") args = parser.parse_args(['--foo', 'Foo', '--bar', 'Bar']) # Namespace(bar='Bar', foo='Foo') args = parser.parse_args(['--foo', 'Foo']) # Namespace(bar='Foo_BAR', foo='Foo') args = parser.parse_args(['--bar', 'Bar', '--foo', 'Foo']) # Namespace(bar='Bar', foo='Foo') 

Note that the class must know the dest argument to --bar . In addition, I use '%s_BAR' to easily distinguish between the default value and the default value. This handles the case when --bar appears before --foo .

All that complicates this approach:

  • default values ​​are evaluated at add_argument time.
  • default values ​​are placed in the namespace at the beginning of parse_args .
  • tagged (optional) arguments can occur in any order
  • the Action class is not intended to handle interacting arguments.
  • The bar action will not be called in the default case.
  • The default bar value may be a function, but after parse_args you need to check if it needs to be evaluated or not.

While this regular action does the trick, I still think the addbar function in my other answer is a cleaner solution.

+3
source share

I would, as a first attempt, get this working using the after-argparse function.

 def addbar(args): if args.bar is None: args.bar = args.foo+'_BAR' 

If this action needs to be reflected in help , put it there yourself.

In theory, you can write a custom Action for foo , which also set the value to bar . But this requires more familiarity with the Action class.

I tried a custom Action that configures the default bar action, but it is complicated. parse_args uses the default values ​​at the beginning before it acts on any of the arguments.

+4
source share

All Articles