argparse default option based on another option

后端 未结 2 781
面向向阳花
面向向阳花 2020-12-18 17:59

Suppose I have an argparse python script:

import argparse
parser = argparse.ArgumentParser()

parser.add_argument(\"--foo\", required=True)

2条回答
  •  一向
    一向 (楼主)
    2020-12-18 18:18

    Here's another attempt at writing 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 has to know the dest of the --bar argument. Also I use a '%s_BAR' to readily distinguish between a default value, and a non default one. This handles the case where --bar appears before --foo.

    Things that complicate this approach are:

    • default values are evaluated at add_argument time.
    • default values are placed in the Namespace at the start of parse_args.
    • flagged (optionals) arguments can occur in any order
    • the Action class is not designed to handle interacting arguments.
    • the bar action will not be called in the default case.
    • the bar default could be a function, but something would have to check after parse_args whether it needs to be evaluated or not.

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

提交回复
热议问题