Ronald
Ronald

Reputation: 33

Using argparse to create custom command line formats

I realize that the question is rather general but I didn't know exactly how to ask it for what I am doing, but here goes.

I want to create a tool that allows option in the following format which also uses custom actions:

tool.py {start|stop|restart|configure}

Each of the above commands are mutually exclusive and some can have separate unique options. All will call a custom action (subclassed argparse.Action).

tool.py start

The above will do nothing because no arguments (via "add_argument()") was defined.

I though about making a subparser, but doing so doesn't work initially unless you set default arguments, via "set_defaults()". However, doing this and setting:

class CustomAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        print('Args: %r %r %r' % (namespace, values, option_string))
        setattr(namespace, self.dest, values)

parser = argparse.ArgumentParser(help="Basic daemon.")
subparsers = parser.add_subparsers()
start_parser = subparsers.add_parser("start")
start_parser.set_defaults(start=True, action=CustomAction)

doesn't seem to kick off the custom action as expected. Below is the output I get:

$ custom_parser.py start
Namespace(action=<class '__main__.BasicAction'>, start=True)

I can see that the values are being assigned, but NOT called.

I basically want to have exclusive parent options that can be specified without child argument but still allow exclusive sub-arguments like so, if desired:

tool.py configure {interval|recipients}

Any ideas?

Upvotes: 1

Views: 1235

Answers (1)

Greg
Greg

Reputation: 5588

You can use subparsers coupled with default functions

def start_something():
    do_starting_actions()

def stop_something():
    do_terminal_actions()

def parse_args():
    parser = ArgumentParser()
    subparsers = parser.add_subparsers()
    start = subparsers.add_parser("start")
    start.set_defaults(func=start_something)
    stop = subparsers.add_parser("stop")
    stop.set_defaults(func=stop_something)
    # ...
    return parser.parse_args()

def main():
    args = parse_args()
    args.func()

Then you can call the parser from the command line

mymodule.py start

If you wanted to extend the subparser you could do it like:

start = subparsers.add_parser("start")
start.add_argument("--foo")

Upvotes: 2

Related Questions