18

I am adding subparsers to my parser to simulate subcommands functionality (for example code see: Simple command line application in python - parse user input?). Now I want to add a quit subparser/command that takes no arguments and has a "quit" action attached. Is it possible ? How can I go about it ?

1 Answer 1

28

The documentation for subcommands gives two examples of how to identify the subparser.

https://docs.python.org/dev/library/argparse.html#sub-commands

One is to give the add_subparsers a dest:

def do_quit(args):
    # action
    quit()

parser = ArgumentParser()
subparser = parser.add_subparsers(dest='cmd')
....
subparser.add_parser('quit')
...
args = parser.parse_args()
print args.cmd   # displays 'quit'
if args.cmd == 'quit':
   do_quit(args)

the other is to use set_defaults to link the subparser with a function:

parser = ArgumentParser()
subparsers = parser.add_subparsers()
...
parser_quit = subparsers.add_parser('quit')
parser_quit.set_defaults(func=do_quit)
...
args = parser.parse_args()
args.func(args)

On further thought, here's a way, using a custom Action. It is like _HelpAction (which is used by a -h). It's called by a positional argument with nargs=0 (or '?'). Such an argument is always called, even though there are no strings to match it (or rather, 0 strings match it). This a logical, but somewhat obscure, consequence of how positionals are handled.

class QuitAction(argparse.Action):
    def __call__(self, parser, *args, **kwargs):
        parser.exit(message="QUITTING\n")

p=argparse.ArgumentParser()
sp=p.add_subparsers(dest='cmd')
p1=sp.add_parser('quit')
p1.add_argument('foo', action=QuitAction, nargs='?', help=argparse.SUPPRESS)
p.parse_args(['quit'])

producing (when run in Ipython):

QUITTING
An exception has occurred, use %tb to see the full traceback.    
SystemExit: 0
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! If you have a look at the linked code: stackoverflow.com/questions/25332925/… you will see that I want the parsing to take place automatically - I do not want to add logic outside the parser. No other way ? Can I add a "quit" argument to the main parser (no -quit that is) ? edit: github
Sure - a ArgumentParser subclass that redefines parse_args. It would first call super().parse_args (or parse_known_args) and then perform the 'logic outside the parser'. Only you would know exactly what is hidden behind that method definition.
I added a method using an optional postional argument.
Thanks ! I already have a parse method - I can do that. Re: the nargs hack: how can I then prevent the foo argument to show up in quit's help ?
Hmm - I get usage: sync quit [-h] dummy sync quit: error: too few arguments in Python 2.7.8 (dummy is foo, sync is the prog) - EDIT: nargs='?' fixed that ! - you should edit your answer probably
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.