CLI applications in Python with Click
Tags: python, beginners, tutorial, codenewbie
Published: 2020-03-18 13:11:36

What happens when you're in quarantine and got nothing to do?

You code, of course. And we are back again with another tutorial-ish article about how to make CLI applications in Python with the [Click](https://github.com/pallets/click) library. This should be enough to get you started building your own CLI applications using Click.

##What we'll be making
We'll be making a madlibs program that takes text input and makes a madlib.

```
    __  ___          _____ __            ________    ____
   /  |/  /___ _____/ / (_) /_  _____   / ____/ /   /  _/
  / /|_/ / __ `/ __  / / / __ \/ ___/  / /   / /    / /  
 / /  / / /_/ / /_/ / / / /_/ (__  )  / /___/ /____/ /   
/_/  /_/\__,_/\__,_/_/_/_.___/____/   \____/_____/___/   


Enter an animal: Flamingo
Enter a food: Hamburger
Enter a city: New Jersey

Once upon a time, deep in an ancient jungle,
there lived a flamingo.  This flamingo
liked to eat hamburger, but the jungle had
very little hamburger to offer.  One day, an
explorer found the flamingo and discovered
it liked hamburger.  The explorer took the
flamingo back to New jersey, where it could
eat as much hamburger as it wanted.  However,
the flamingo became homesick, so the
explorer brought it back to the jungle,
leaving a large supply of hamburger.

The End
```
##Overview
Before we begin, it's advisable to create a virtual environment. Since this is a very simple application, we are only going to need one python file, not including the virtual environment. We will be using Click for the CLI and pyFiglet for that fancy ASCII lettering. You can install them by using pip with your virtual environment active, 
```
pip install Click, pyfiglet
```

In the same directory, create a new file called madlibs.py and paste the following code,
```
import click
from pyfiglet import Figlet

f = Figlet(font='slant')
print(f.renderText("Madlibs CLI"))

@click.command()
@click.option('--animal', prompt='Enter an animal', help='Name of an animal')
@click.option('--food', prompt='Enter a food', help='Name of a food')
@click.option('--city', prompt='Enter a city', help='Name of a city')
def madlibs(animal, food, city):
    '''
    A CLI application that takes the name of an animal, food and place to make up a madlib.
    '''
    story = f"""
Once upon a time, deep in an ancient jungle,
there lived a {animal.lower()}.  This {animal.lower()}
liked to eat {food.lower()}, but the jungle had
very little {food.lower()} to offer.  One day, an
explorer found the {animal.lower()} and discovered
it liked {food.lower()}.  The explorer took the
{animal.lower()} back to {city.capitalize()}, where it could
eat as much {food.lower()} as it wanted.  However,
the {animal.lower()} became homesick, so the
explorer brought it back to the jungle,
leaving a large supply of {food.lower()}.

The End
            """

    click.echo(story)


if __name__ == "__main__":
    madlibs()
```
##What's happening here?
The first two lines import each of the packages. 

Click is based on declaring commands through decorators. Here, `@click.command()` is the decorator which converts a function into a command line tool. To put it simply, `@click.command()` turns the function `madlibs()` into a callable script. You can try doing,
```
@click.command()
def madlibs():
    click.echo('Madlibs!')
```
And it will print out the statement on the console by invoking the function as a command.

`@click.option()` is used to pass optional parameters to the function. In this case, we are passing the names of an animal, food and city. The good thing about Click is that it automatically generates help text for you, and it's easily customizable. As you can see here,
```
@click.option('--animal', prompt='Enter an animal', help='Name of an animal')
```
and the script description added within the function,
```
def madlibs(animal, food, city):
    '''
    A CLI application that takes the name of an animal, food and place to make up a madlib.
    '''
    .
    .
```
If you type `python madlibs.py --help`, you will be shown the following,
```
    __  ___          _____ __            ________    ____
   /  |/  /___ _____/ / (_) /_  _____   / ____/ /   /  _/
  / /|_/ / __ `/ __  / / / __ \/ ___/  / /   / /    / /
 / /  / / /_/ / /_/ / / / /_/ (__  )  / /___/ /____/ /
/_/  /_/\__,_/\__,_/_/_/_.___/____/   \____/_____/___/


Usage: madlibs.py [OPTIONS]

  A CLI application that takes the name of an animal, food and place to make
  up a madlib.

Options:
  --animal TEXT  Name of an animal
  --food TEXT    Name of a food
  --city TEXT    Name of a city
  --help         Show this message and exit.
```
Neat, huh!

It is advised to use `setuptools` if you plan on sharing it as a proper CLI application. Read more on setuptools integration in the [official docs](https://click.palletsprojects.com/en/7.x/setuptools/#setuptools-integration).

Until next time.

TL;DR to the code,
{% github Blazephoenix/python-cli-apps no-readme %}