How to Create Your Own Command Line Programs in Python With Click
Click is a Python package for writing command line interfaces. It produces beautiful documentation for you and lets you build command line interfaces in as little as one line of code. In short: it’s awesome and can help take your programs to the next level.
Here’s how you can use it to liven up your Python projects.
Writing Command Line Programs Without Click
It’s possible to write command line programs without using Click, but doing so requires more effort and lots more code. You need to parse command line arguments, perform validation, develop logic to handle different arguments, and build a custom help menu. Want to add a new option? You’ll be modifying your help function then.
There’s nothing wrong with writing your own code, and doing so is a great way to learn Python, but Click allows you to follow the “Don’t Repeat Yourself” (DRY) principles. Without Click, you’ll write code which is fragile and requires lots of maintenance whenever any changes happen.
Here’s a simple command line interface coded without Click:
import sys
import random
def do_work():
""" Function to handle command line usage"""
args = sys.argv
args = args[1:] # First element of args is the file name
if len(args) == 0:
print('You have not passed any commands in!')
else:
for a in args:
if a == '--help':
print('Basic command line program')
print('Options:')
print(' --help -> show this basic help menu.')
print(' --monty -> show a Monty Python quote.')
print(' --veg -> show a random vegetable')
elif a == '--monty':
print('What\'s this, then? "Romanes eunt domus"? People called Romanes, they go, the house?')
elif a == '--veg':
print(random.choice(['Carrot', 'Potato', 'Turnip']))
else:
print('Unrecognised argument.')
if __name__ == '__main__':
do_work()
These 27 lines of Python work well but are very fragile. Any change you make to your program will need lots of other supporting code to change. If you change an argument name you’ll need to update the help information. This code can easily grow out of control.
Here’s the same logic with Click:
import click
import random
@click.command()
@click.option('--monty', default=False, help='Show a Monty Python quote.')
@click.option('--veg', default=False, help='Show a random vegetable.')
def do_work(monty, veg):
""" Basic Click example will follow your commands"""
if monty:
print('What\'s this, then? "Romanes eunt domus"? People called Romanes, they go, the house?')
if veg:
print(random.choice(['Carrot', 'Potato', 'Turnip']))
if __name__ == '__main__':
do_work()
This Click example implements the same logic in 16 lines of code. The arguments are parsed for you, and the help screen is generated:
This basic comparison shows how much time and effort you can save by using programs such as Click. While the command line interface may appear the same to the end user, the underlying code is simpler, and you’ll save lots of time coding. Any changes or updates you write in the future will also see significant development time increases.
Getting Started With Click for Python
Before using Click, you may wish to configure a virtual environment. This will stop your Python packages conflicting with your system Python or other projects you may be working on. You could also try Python in your browser if you want to play around with Python and Click.
Finally, make sure you’re running Python version 3. It’s possible to use Click with Python version 2, but these examples are in Python 3. Learn more about the differences between Python 2 and Python 3.
Once ready, install Click from the command line using PIP (how to install PIP for Python):
pip install click
Writing Your First Click Program
In a text editor, start by importing Click:
import click
Once imported, create a method and a main entry point. Our Python OOP guide covers these in greater detail, but they provide a place to store your code, and a way for Python to start running it:
import click
import random
def veg():
""" Basic method will return a random vegetable"""
print(random.choice(['Carrot', 'Potato', 'Turnip', 'Parsnip']))
if __name__ == '__main__':
veg()
This very simple script will output a random vegetable. Your code may look different, but this simple example is perfect to combine with Click.
Save this as click_example.py, and then run it in the command line (after navigating to its location):
python click_example.py
You should see a random vegetable name. Let’s improve things by adding Click. Change your code to include the Click decorators and a for loop:
@click.command()
@click.option('--total', default=3, help='Number of vegetables to output.')
def veg(total):
""" Basic method will return a random vegetable"""
for number in range(total):
print(random.choice(['Carrot', 'Potato', 'Turnip', 'Parsnip']))
if __name__ == '__main__':
veg()
Upon running, you’ll see a random vegetable displayed three times.
Let’s break down these changes. The @click.command() decorator configures Click to work with the function immediately following the decorator. In this case, this is the veg() function. You’ll need this for every method you’d like to use with Click.
The @click.option decorator configures click to accept parameters from the command line, which it will pass to your method. There are three arguments used here:
- –total: This is the command line name for the total argument.
- default: If you don’t specify the total argument when using your script, Click will use the value from default.
- help: A short sentence explaining how to use your program.
Let’s see Click in action. From the command line, run your script, but pass in the total argument like this:
python click_example.py --total 10
By setting –total 10 from the command line, your script will print ten random vegetables.
If you pass in the –help flag, you’ll see a nice help page, along with the options you can use:
python click_example.py --help
Adding More Commands
It’s possible to use many Click decorators on the same function. Add another click option to the veg function:
@click.option('--gravy', default=False, help='Append "with gravy" to the vegetables.')
Don’t forget to pass this into the method:
def veg(total, gravy):
Now when you run your file, you can pass in the gravy flag:
python click_example.py --gravy y
The help screen has also changed:
Here’s the whole code (with some minor refactoring for neatness):
import click
import random
@click.command()
@click.option('--gravy', default=False, help='Append "with gravy" to the vegetables.')
@click.option('--total', default=3, help='Number of vegetables to output.')
def veg(total, gravy):
""" Basic method will return a random vegetable"""
for number in range(total):
choice = random.choice(['Carrot', 'Potato', 'Turnip', 'Parsnip'])
if gravy:
print(f'{choice} with gravy')
else:
print(choice)
if __name__ == '__main__':
veg()
Even More Click Options
Once you know the basics, you can begin to look at more complex Click options. In this example, you’ll learn how to pass in several values to a single argument, which Click will convert to a tuple. You can learn more about tuples in our guide to the Python dictionary.
Create a new file called click_example_2.py. Here’s the starter code you need:
import click
import random
@click.command()
def add():
""" Basic method will add two numbers together."""
pass
if __name__ == '__main__':
add()
There’s nothing new here. The previous section explains this code in detail. Add a @click.option called numbers:
@click.option('--numbers', nargs=2, type=int, help='Add two numbers together.')
The only new code here are the nargs=2, and the type=int options. This tells Click to accept two values for the numbers option, and that they must both be of type integers. You can change this to any number or (valid) datatype you like.
Finally, change the add method to accept the numbers argument, and do some processing with them:
def add(numbers):
""" Basic method will add two numbers together."""
result = numbers[0] + numbers[1]
print(f'{numbers[0]} + {numbers[1]} = {result}')
Each value you pass in is accessible through the numbers object. Here’s how to use it in the command line:
python click_example_2.py --numbers 1 2
Click Is the Solution for Python Utilities
As you’ve seen, Click is easy to use but very powerful. While these examples only cover the very basics of Click, there are lots more features you can learn about now that you have a solid grasp of the basics.
If you’re looking for some Python projects to practice your new found skills with, why not learn how to control an Arduino with Python, or how about reading and writing to Google Sheets with Python? Either of these projects would be perfect for converting to Click!
Read the full article: How to Create Your Own Command Line Programs in Python With Click