Creating a Python command line application
Question: So I wrote a Python 3 library, which serves as an application 'backend'. Now I
can sit down with the interpreter, import the source file(s), and hack around
using the lib - I know how to do this.

But I would also like to build a command line 'frontent' application using the
library. My library defines a few objects which have high-level commands,
which should be visible by the application. Such commands may return some data
structures and the high-level commands would print them nicely. In other
words, the command line app would be a thin wrapper around the lib, passing
her input to the library commands, and presenting results to the user.

The best example of what I'm trying to achieve would probably be Mercurial
SCM, as it is written in Python and the 'hg' command does what I'm looking for
- for instance, 'hg commit -m message' will find the code responsible for the
'commit' command implementation, pass the arguments from the user and do its
work. On the way back, it might get some results and print them out nicely.

Is there a general way of doing it in Python? Like exposing
classes/methods/functions as 'high level' commands with an annotation? Does
anybody know of any tutorials?


Answer: You can do this with
[`argparse`](https://docs.python.org/3/howto/argparse.html). For example here
is the start of my [`deploy`](https://github.com/rsmith-nl/deploy) script.

    
    
    def main(argv):
        """
        Entry point for the deploy script.
    
        Arguments:
            argv: All command line arguments save the name of the script.
        """
        parser = argparse.ArgumentParser(description=__doc__)
        parser.add_argument('-v', '--verbose', action='store_true',
                            help='also report if files are the same')
        parser.add_argument('-V', '--version', action='version',
                            version=__version__)
        parser.add_argument('command', choices=['check', 'diff', 'install'])
        fname = '.'.join(['filelist', pwd.getpwuid(os.getuid())[0]])
        args = parser.parse_args(argv)
    

It uses an argument with choices to pick a function. You could define a
dictionary mapping choices to functions;

    
    
    cmds = {'check': do_check, 'diff': do_diff, 'install': do_install}
    fn = cmds[args.command]
    

If you make sure that all the dict keys are in the command choices, you don't
need to catch `KeyError`.

