cft

How To Create a CLI App in Python

The easy way to transform your script into a CLI in few lines


user

Fernando Souza

a year ago | 3 min read

Python is an amazing and versatile programming language. You can build a variety of applications, from web scrapping to beautiful desktop app.

And in most of the time, you will only need the standard library to execute your tasks. But sometimes, using an extra package can be very useful, to abstract a functionality and save you precious time.

Building a command line interface is no different. Although we have the option to use the standard library to do it (using argparse or getopt), we can use other packages to help us to create a complete CLI application.

There are some great options out there if you want to create, like cliffcement, and click.

But today I want to talk about Typer.

Note: this article was created and tested with Python 3.8.5 and Ubuntu 20.04.

Installation

To install, simply run the command:

pip install typer

Typer

Developed by the same creator of FastAPI, it uses the package Click (that you should also check, by the way) and expands it.

It creates the parsers and the arguments directly from the parameters of your function, with the help of python type hints.

You can expose a function as a command line application with just a line:

import typer

def hello(name: str):
typer.echo(f'Hello, {name}')

if __name__ == '__main__':
typer.run(hello)

What the typer.run function does is to create the minimum that a CLI application needs:

  • An error message:
  • And a help message:

It automatically discovers all the parameters of your function. And with the help of python typing hint, the correct type as well.

Example

Let’s create an example to show three main features of Typer:

  • Documentation through docstrings.
  • Optional arguments.
  • Multiple commands.

Note: this example uses the Pillow package.

In this example, we are going to create two commands: stats and resize. They will show basic information about an image and resize it to a new width and height, respectively.

import typer
from PIL import Image

cli = typer.Typer()

@cli.command()
def stats(filename: str):
'''
Show image info for FILENAME
'''
img = Image.open(filename)

# Print properties
typer.echo(f' Format:\t {img.format}')
typer.echo(f' Mode:\t {img.mode}')
typer.echo(f' Size:\t {img.size[0]} x {img.size[1]}')
typer.echo(f'Palette:\t {img.palette}')


@cli.command()
def resize(filename: str, width: int, heigth: int, out: str = 'out.jpg'):
'''
Resize FILENAME with new WIDTH and HEIGHT.

The output filename will be "out.jpg" if not specified by --out.
'''
img = Image.open(filename)
resized = img.resize((width, heigth), Image.LANCZOS)
resized.save(out)
typer.echo(f'New image saved {out} with size {width}x{heigth}')


if __name__ == '__main__':
cli()

To create multiple commands, we have to create a new Typer object through typer.Typer(). Then we use the decorator command to indicate to Typer that the function must be added as a command.

The syntax for a CLI command is something like this:

optimize.py [OPTIONS] COMMAND [ARGS]...

In our case, the commands will be exactly the name of the functions we declared, stats and resize. Since we declared some docstring to each function, we can access it through option --help after each command:

python optimize.py COMMAND --help

In the case of the command resize, we have an optional argument called out. An optional argument is, as the name says, optional. To Typer, every function parameter that has a default value will be considered an option.

As an option, you don’t need to follow an specific order to declare it and will be preceded with -- followed by the name of the parameter. In our case, it will be --out.

Conclusion

Creating a CLI is useful when you want to use a script, specially with Python. Although you can create using standard libraries, such as argparse, sometimes is easier to use a third-party library.

Typer is great library that will help you transform your script to a command line application. Documentation, arguments parsers, options, help messages, are all easily handled by them, without you have to worry too much.

Check out their documentation for more advanced options and configuration.

Hope you enjoyed reading this article. Happy coding!

Upvote


user
Created by

Fernando Souza


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles