Build Interactive CLI Tools in Python

Bored of traditional CLIs? Develop interactive command lines with PyInquirer

Dinesh Kumar K B
Geek Culture
5 min readJan 24, 2021

--

Photo by Sigmund on Unsplash

Note:For non-members, this article is also available at https://dineshkumarkb.com/tech/how-to-build-interactive-command-line-tools-in-python/

Introduction:

Command-line interfaces are quick and efficient tools to accomplish tasks. Not only that, but it’s also cool to have a command-line interface for any web application you develop to avoid having the end-user getting lost in the vast UI sitemap.

That’s why despite having a feature-rich console, aws has an amazing cli backed by its botocore module doesn’t it?

Motivation:

  1. Are you bored of the traditional cli’s?
  2. Are you bored of documenting the commands for every single feature in the cli?

If yes, then you should definitely read further.

We can build interactive and immersive command-line interfaces in python using PyInquirer and other libraries.

For my example, I am picking click and PyInquirer.

A quick introduction to Click:

Click was written to support the Flask web framework in python. Flask’s command line’s use clicks to perform their operations.

Have you ever tried adding values to a database in a flask from the command-line? Well, then you have used click.

Why not argparse?

We could very well write a simple calculator cli with argparse. In my opinion, maintaining the code written in argparse gets complicated as the cli application grows. Whereas using click, the code looks more modular and scalable. So am choosing to click here.

You are free to choose any cli framework of your choice or even just settle with PyInquirer alone.

Installing Click

pip install click

Now that we have completed the installation, let’s write a simple calculator cli using click.

This is one way of writing a simple calculator cli. Let’s execute the help command for this cli.

Output:python simplecalc.py --help
Usage: simplecalc.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
add
div
mul
sub

The help command’s output looks something like this. We will perform one add operation.

Output:python simplecalc.py add
Enter the first number: 2
Enter the second number: 2
The added value 4

This is fairly good. With this, the user has to either remember the command or check the help to get the available cli options. This gets even more cluttered when you have multiple commands with nested sub-commands.Users may find it difficult to remember every single command and its corresponding sub-command. Also, last but not least we as a developer may have to write a comprehensive help command accordingly.

An alternative to this is an interactive cli using PyInquirer. Let’s install the PyInquirer.

pip install PyInquirer

Introducing PyInquirer:

PyInquirer strives to be an easily embeddable and beautiful command-line interface for Python. PyInquirer works based on the questions that can be prompted to a user instead of the user providing the cli commands. It helps us write immersive command-line tools.

PyInquirer lets

  • you define a list of questions and hand them to prompt
  • prompt returns a list of answers

It supports the following question types

  • List
  • Raw List
  • Expand
  • Confirm
  • CheckBox
  • Input
  • Password
  • Editor

Examples for all these question types are provided here. I believe most of the question types are pretty self-explanatory.

Now, let’s rewrite the simple calculator program using PyInquirer.

Simple Calculator Using PyInquirer:

Interactive Simple Calculator

Understanding PyInquirer:

The type of the question defines what kind of prompt the user gets. If the type is defined as a list, we get a list of options, whereas when it is an input, we prompt the user to get the input and so on.

In the above code snippet, the question is a list of dictionaries with type, name, message, validate, filter, and few more question properties. Let’s look at the properties used.

type — Defines the type of question. Could be an input, a list of questions, a password prompt, etc. We have used a list here to provide the user a list of calculator options instead of letting the user provide the command for us. Pretty cool isn’t it? This was the first thing that attracted me.

Type-list

This also provides a visual cue to notify the user what option is being selected.

Note: Please be informed that the look and feel may vary based on the platform. I am using an ubuntu system.

name — Name is the variable that stores the option selected by the user. For instance, if the user selects product in the above list, the user_option variable will have the value product.

input — Input is similar to regular python inputs which prompt the user to enter a value.

Type-Input

message — Message is the message displayed to the user.

validate — Validate usually calls a Validator class to check the user’s input. For instance, we are expecting an int value here.

What if the user provides a string or a None value? Shouldn’t we validate the user’s input? That’s exactly what validates is used for. You can have your validation logic here.

InputValidation

filter — Any user value entered in input will be of type strby default. If we need to convert them to an int or any other type we could leveragefilter function to do that. This could also be used to strip white spaces if any from the user’s input.

PyInquirer can be extended for any complex CLIs and attract more users for your cli.

The overall execution looks something like below.

Output:

Next time when you develop or enhance a command-line tool, definitely give this a try.

References:

--

--