A Beautiful Python Commandline Interface

The most elegant solutions are often to problems you didn’t even realize you had.

Just a few weeks ago I commented on how easy it is to create a good commandline interface with the argparse library. The code I used to demonstrate this looked like this:

parser = argparse.ArgumentParser(description="Scrapes comments for a reddit user. Currently limited to most recent 999 comments (limit imposed by reddit).")
parser.add_argument('-u','--user', type=str, help="Reddit username to grab comments from.", required=True)
parser.add_argument('-l','--limit', type=int, help="Maximum number of comments to download.", default=0)
parser.add_argument('-d','--dbname', type=str, help="Database name for storage.", default='RedditComments.DB')
parser.add_argument('-w','--wait', type=str,help="Wait time between GET requests. Reddit documentation requests a limit of 1 of every 2 seconds not to exceed 30 per min.", default=2)

args = parser.parse_args()
_user   = args.user
_limit  = args.limit
_dbname = args.dbname
_wait   = args.wait

Which, in all fairness, is not bad, and produces the following output (which could be a little prettier):

$ python testargs.py

usage: test_args.py [-h] -u USER [-l LIMIT] [-d DBNAME] [-w WAIT]

Scrapes comments for a reddit user. Currently limited to most recent 999
comments (limit imposed by reddit).

optional arguments:
-h, --help                 show this help message and exit
-u USER, --user USER       Reddit username to grab comments from.
-l LIMIT, --limit LIMIT    Maximum number of comments to download.
-d DBNAME, --dbname DBNAME Database name for storage.
-w WAIT, --wait WAIT       Wait time between GET requests. Reddit documentation
requests a limit of 1 of every 2 seconds not to exceed 30 per min.

Part of what makes this easy to read is that it’s familiar: this isn’t some commandline vocabulary I just invented, it conforms to the POSIX standard.

Yesterday, I saw a PyCon UK presentation by Vladimir Keleshev describing a new library he had written called docopt. The genius of this library is that it speaks POSIX. Instead of feeding a whole list of complex parameters to define a single argument, or worse, a relationship between arguments (such as mutual exclusivity), all you have to do is pass docopt the help text you want it to produce, and it handles the rest.

If your commandline arguments will have complex relationships, or there are several exclusive use cases for your program that need to be defined, this is an incredible elegant and convenient solution.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s