argparse: usage reporting for individual choices of a positional argument?
Question: I'm trying to refactor a program to use the new standard argparse module.
Given the structure below, should I be using
[choices](http://docs.python.org/library/argparse.html#choices) for the
primary positional argument,
[subcommands](http://docs.python.org/library/argparse.html#sub-commands), or
some other method?

    
    
    foo [OPTION]... COMMAND [PACKAGE(S)]...
    
    Commands:
        available -  show packages available to be installed
        install   -  download and install packages, including dependencies
        remove    -  uninstall packages
        ...snip
        version   -  display installed version of package
    
    Options:
        -d,--download          download only
        -i,--ini=FILE          use alternate setup.ini
        ...snip
    

Choices example, concise & clear, but no usage help for each command:

    
    
    parser = argparse.ArgumentParser()
    commands = "available install remove ... version".split()
    parser.add_argument('command', choices=commands, 
        help="generic help for all 12 commands goes here")
    

Choices is logically more in tune with the program, as what comes after the
command on the command line is largely the same for all of them. While
subcommands seems to wants me to treat each command one as world mostly to
itself and involves 3 times the code. However there doesn't seem to be a
method to display usage for each choice in choices(?) Perhaps there's a third
route I'm not seeing?

I'm using python 2.7.


Answer: I'd go with the [sub-
commands](http://docs.python.org/library/argparse.html#sub-commands) option.

You wont necessarily need to code more: build commands classes, each one
carrying its own setting (using inheritance where needed), in your `Main` cli
class instantiate the main parser and then hand it over to the commands that
will care to add/set their own
[subparser](http://docs.python.org/library/argparse.html#argparse.ArgumentParser.add_subparsers).

The answer is short, but if it's not clear tell me and I'll add a code sample.

* * *

### Rough Example

You should build your commands as classes:

    
    
    class Install(BaseCommand):
    
        help = "download and install packages"
    
        @classmethod
        def interface(cls, cmd_parser):
            cmd_parser.add_argument('--foo')
            cmd_parser.set_defaults(cmd=cls)    # this line is very important
    
        def start(self, foo=None):
            # command execution
    

And your command line interface should be a class too:

    
    
    class Main(BaseCli):
    
        def __init__(self):
            self.commands = [Install]   # just the command classes
    
            self._parser = argparse.ArgumentParser()
            self._subparsers = self._parser.add_subparsers()
    
        def load_interface(self):
            for cmd in self.commands:
                cmd_parser = self.add_command_parser(help=cmd.help)
                cmd.interface(cmd_parser)
    
        def add_command_parser(self, *args, **kwargs):
            return self._subparsers.add_parser(*args, **kwargs)
    
        def parse_args(self, args=None, namespace=None):
            return self._parser.parse_args(args, namespace)
    
        def start_session(self, namespace):
            # this will instantiate the appropriate command class
            cmd = namespace.cmd()
            # and call its start method with the user args
            cmd.start(**namespace.__dict__)
    

To be used like this:

    
    
    cli = Main()
    cli.load_interface()
    args = cli.parse_args()
    cli.start_session(args)
    

Notice that with this approach you'll have all the power of inheritance by
your side! :)

