Build Interactive CLI Tools in Python
Bored of traditional CLIs? Develop interactive command lines with PyInquirer
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:
- Are you bored of the traditional cli’s?
- 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:
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.
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.
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.
filter — Any user value entered in input will be of type str
by 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.