Building command line interfaces in Python
It is very useful to be able to create command line interfaces for our programs. There are several situations in which we want to do that:
- Building standalone command-line applications like file managers, editors and other full-featured apps
- Building one-off automated scripts which can run multiple tasks and take complex parameters
- Creating utility tools that can be invoked from the terminal, but are integrated in our programs that are otherwise not CLI-based, e.g. creating useful tasks in our web applications like basic setup procedure, checks, code generators and so on
Python standard library provides us with the basic building blocks to create simple command-line interfaces such as argparse to read command-line arguments passed to our Python file, input for interactivity and print function to make simple outputs.
However even for simple scripts I recommend to use one of the many available libraries unless we cannot install additional dependencies in our environment. They pack a lot of useful stuff that we will definitely want to use and make the process of creating CLIs a piece of cake.
Click
My first recommendation is Click. Click is simple to use CLI library and comes already with support for coloring output, showing progress bars and it can even open editors for multi-line text editing. It has one other advantage. Due to its popularity it is included in some tools that we might be using already. Frameworks Flask and FastAPI are notable examples where we can use Click right away without installing it. We can also add some simple additions like tabulate to produce simple tables in the terminal.
Rich
If simple colors won’t cut it, there is this neat library called Rich. Rich is basically print() function on steroids. It can pretty-print Python lists and collections, output emojis, render Markdown and even highlight source code!
Let’s see an example of Click and Rich libraries together in action to setup a simple program with progress bar, table and colors:
"""Example of using libraries Click and Rich to create CLI"""
import time
import click
from rich.console import Console
from rich.table import Column, Table
console = Console()
@click.group()
def cli():
pass
def get_length(word: str) -> int:
time.sleep(1)
return len(word)
@cli.command()
@click.argument('words', nargs=-1)
def compute(words):
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Word", style="dim", width=12)
table.add_column("Length")
with click.progressbar(words) as click_words:
for word in click_words:
word_length = get_length(word)
table.add_row(word, str(word_length))
console.print(table)
if __name__ == "__main__":
cli()
Typer
Typer is a CLI tool built on Click which enables us to leverage Python typing to define command line arguments instead of using decorators. Let’s see a simple example of taking arguments and using them:
import typer
app = typer.Typer()
@app.command()
def display(color: str, reverse: bool = True):
message = f"Hello from typer using {color} color!"
if not reverse:
typer.echo(typer.style(message, fg=color))
else:
typer.echo(typer.style(message[::-1], fg=color))
if __name__ == "__main__":
app()
Both Click and Typer can automatically display help to users of our programs using --help
option.
You can run both examples from the Github repo.
There are countless CLI tools for Python but I believe that Click, Rich and Typer will cover most of our needs for simple CLI programs that we typically build.
Last updated on 30.1.2020.