Writing a simple Python CLI script

Over the past few days I’ve been obsessively reading all I can find about Python. For years and years I’ve avoided learning Python on the trivial grounds that white-space defined code blocks just seemed like a recipe for disaster to me. But… it turns out if you get over that initial hurdle the language is a pleasure to use. It reminds me very much of learning to code using BASIC in the long long ago. Python.org is the official website if you’re interested in finding out more. The documentation section has a decent tutorial and links to loads of great resources. According to the latest TIOBE index Python is the third most popular language in the world behind C and Java, so it’s well worth learning.

I like to mess about on the command line, so writing a command line tool seems like a great project. ivermectin dose for goats with mites by mouth Let’s dive in.

Here’s our initial script:

#!/usr/bin/env python3        # run the script with Python 3

print('Hello world')

Let’s save that as helloworld.py.

Making the script executable

To run this script we type python3 helloworld.py at the command prompt in the directory where we saved it.

If you’re on Linux you can also run it directly by typing ./helloworld at the shell prompt, but that won’t work initially because the script is not executable. To make the script executable we run the command chmod +x helloworld.py. Now when we type ./helloworldthe script will run.

$ chmod +x helloworld.py 
$ ./helloworld.py
Hello World

Nicer invocation

I don’t want to have to cd into my directory every time I want to greet the world. Command line tools like grep and ls can be invoked just by typing their names, I want to do the same. On Linux this stuff is easy. If you’re on Windows, what are you doing you psychopath? Also I have no idea how to help you, but the answers to this stackoverflow question might be useful.

  • First let’s rename our script from helloworld.py to just helloworld. This is not really necessary but it means that we can just type helloworld at the command line rather than helloworld.py, which makes it feel more like a shell command.
  • Next, if we haven’t already done so we make the script executable like so: chmod +x helloworld
  • FInally we either
    • Put the script in some directory which is already on our $PATH
    • or we can add the directory where the script lives to our $PATH. I chose this option as I don’t want to pollute my nice Linux install with my own weird scripts. You can look up the procedure for adding a directory to you $PATH for your particular distro, for myself on Manjaro:
      • I moved the script to the ~/Documents/scripts/ folder.
      • I edited the ~/.profile file and added the line
        export PATH = "$PATH:$HOME/Documents/scripts"
      • I ran the source command to reload the ~/.profile file like so:
        source ~/.profile

Once you have followed these steps you’ll be able to execute your script from any directory just by typing the script name. Tab completion even works.

[davido@david-pc scripts]$ cd ~
[davido@david-pc ~]$ helloworld
Hello world

Adding command line arguments

The python module for command line arguments is called argparse, it’s part of the standard library. It can be a bit clunky to use, there are alternatives, but for our case it’s fine.

Here’s our updated script:

#!/usr/bin/env python3

import argparse

parser = argparse.ArgumentParser()
args = parser.parse_args()

print('Hello world')

If you now run helloworld you’ll still get the exact same output, but try running helloworld -h, you will see something like this:

$ helloworld -h
usage: helloworld [-h]

optional arguments:
  -h, --help  show this help message and exit

You can add other command line arguments relatively easily, just read the docs. As an example let’s add an argument for the user’s name. Our script is now:

#!/usr/bin/env python3

import argparse

parser = argparse.ArgumentParser()

parser.add_argument(
    'name',
    metavar = '<name>',
    nargs = '?',
    help = 'optional name for greeting')

args = parser.parse_args()

if args.name:
    print('Hello', args.name)
else:
    print('Hello world')

Try running helloworld -h and see what the output is. Also try helloworld Floof and helloworld by themselves. Note that if you try a multi-word name you’ll get an error unless you enclose it in quotes like so: helloworld "Floof the Great"

Documentation

Let’s follow best practice and make sure that our code is properly documented. I’m taking the instructions from here, which is a really great resource for pretty much all things Python.

This is a very simple program and Python code is very readable, so we don’t really need to add comments. We should however add a docstring to say what the purpose of the file is. According to the specification:

The docstring of a script (a stand-alone program) should be usable as its “usage” message, printed when the script is invoked with incorrect or missing arguments (or perhaps with a “-h” option, for “help”). Such a docstring should document the script’s function and command line syntax, environment variables, and files. Usage messages can be fairly elaborate (several screens full) and should be sufficient for a new user to use the command properly, as well as a complete quick reference to all options and arguments for the sophisticated user. dogs dose and frequency using diy ivermectin

I’m also gonna refer you to this guide for additional help with when and how and what to document.

One more thing that I want is that the docstring description of the program should be printed as part of the argparse help option. This stackoverflow question provides the necessary information for how to set this up.

Here’s what the script looks like now:

#!/usr/bin/env python3
""" helloworld

greets the world or a specific person if specified in the name argument
"""

import argparse

parser = argparse.ArgumentParser(
    description = __doc__,
    formatter_class = argparse.RawDescriptionHelpFormatter)

parser.add_argument(
    'name',
    metavar = '<name>',
    nargs = '?',
    help = 'optional name for greeting')

args = parser.parse_args()

if args.name:
    print('Hello', args.name)
else:
    print('Hello world')

Conclusion

OK so this was a silly, toy program. But you can see with this how you can set yourself up to write much more powerful scripts. There’s a guide to more powerful CLI interface libraries here.

About the Author