Search code examples
pythonargparse

argparse: Ignore positional arguments if a flag is set?


I want to provide the command with 3 arguments: <version>, <input file> and <output file> under normal usage. Except there's a specific flag --init, which will basically run the program without any input and output file specifications required.

I would therefore ideally have a command which usage is:

py program.py --init

OR

py program.py <version> <input file> <output file>

However, since positional arguments are always required (because all 3 are required in any other circumstance than --init), there seems to be no way to cleanly get this syntax and all I could think of would be to make the 3 positional arguments into an optional flag, raise an exception if the optional flag isn't there when --init is not called. And that all seems ugly.

My code so far:

def get_args():
    parser = argparse.ArgumentParser(description="Tool for FOO-ing a BAR.")
    parser.add_argument(dest="version", help="The version.")
    parser.add_argument(dest="input", help="The input file.")
    parser.add_argument(dest="output", help="The output file.")

    parser.add_argument("-i", "--init", dest="init", action="store_true", help="Foo Init.")

    return parser.parse_args()

To Clarify:
Either all 3 arguments (<version> <input> <output>) MUST be specified.
OR
The program is only ran with --init flag and 0 arguments should be specified.

The program should NOT accept with 0, 1 or 2 arguments specified (without the --init flag).


Solution

  • You can define your own action class:

    class init_action(argparse.Action):
        def __init__(self, option_strings, dest, **kwargs):
            return super().__init__(option_strings, dest, nargs=0, default=argparse.SUPPRESS, **kwargs)
        
        def __call__(self, parser, namespace, values, option_string, **kwargs):
            # Do whatever should be done here
            parser.exit()
    
    def get_args():
        parser = argparse.ArgumentParser(description="Tool for FOO-ing a BAR.")
        parser.add_argument(dest="version", help="The version.")
        parser.add_argument(dest="input", help="The input file.")
        parser.add_argument(dest="output", help="The output file.")
    
        parser.add_argument("-i", "--init", action=init_action, help="Foo Init.")
    
        return parser.parse_args()