Intermediate

There is a simpler way create command line interfaces (CLIs) in python using the click package. When we made CLIs in this article on how to parse arguments we made use of the argparse module. This worked fine but there is also another way we can accomplish this.

Today we will look at a package in Python that gives us the ability to build better more intuitive command line interfaces – the click package. The click package uses decorators as a mechanism to making arguments easier (see our article on the Simple Guide to Decorators)

This article assumes you have already read our articles on command line interfaces.

Overview of Click Command Line Argument Python Package

Click is a package for creating cleaner command line interfaces in a simple way with as little code as necessary. It makes use of the functionality of argparse and the efficiency of decorators.

Before we start using click we have to install it first – it does not come with the standard installation of Python. In your command prompt or terminal, you can install via pip:

pip install click

We will start with something simple – a script that outputs “Hello World!”

import click

@click.command()
def main():
    click.echo("Hello World from click")

if __name__ == "__main__":
    main()

In the code above we:

  • import click package
  • decorate the main function with @click.command() – this gives us access to the modules from click. This turns main into a click command
  • we input click.echo() to display output

When using click it is advisable to use click.echo for output instead of print. click.echo takes into account python 2 and python 3 compatibility

How to add options and arguments to click

A CLI that just outputs “Hello World” which is not that useful. We will look at how we add options and arguments to our program. Let’s make some changes to the code we had before

import click

@click.command()
@click.option('--string', '-s', default='World',
                help='what is to be greeted')
def main(string):
    '''program that greets the user'''
    print("Hello {} from click".format(string))

if __name__ == "__main__":
    main()

We added a click.option() decorator. In it, a flag for the option the CLI accepts (in this case string ), a default value if nothing is passed, and help text giving an explanation of what the option does.

Both the --string and -s flag do the same thing. If we did not use the flag the script would still run because options are optional.

Now, let’s look at an example that uses an argument instead of an option

import click

@click.command()
@click.argument('name')
def main(name):
    '''program that greets the user'''
    print("Hello {}!".format(name))

if __name__ == "__main__":
    main()

Have a look what happens when we run the above script but don’t pass anything

We get an error message telling us that we are missing an argument. An error similar to one we had when we were using argparse

NOTE: options have the choice to be passed or not whereas arguments are mandatory

How to Improve the Execution of the click CLI

The current way we are accessing and executing our CLI will become very tedious for a user – having to type the file extension every time. What if there was a way such that all we had to do was input the name of the file followed by the parameters without extension?

Luckily there is a way – by making our python script executable. It’s a simple process but has to be done accurately.

Start by creating a directory and navigating into it. In your terminal or command prompt

mkdir [directory_name]

cd [directory_name]

In that directory make two python files: setup.py and your primary file; in my case main.py

Add this to the main.py file

import click

@click.command()
def cli():
    """A script to greet a user."""
    click.echo('Hello World!')

Then this to the setup.py file

from setuptools import setup

setup(
    name='main',
    version='0.1',
    py_modules=['main'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        main=main:cli
    ''',
)


The important part is the entry_points :

The first main defines what our program will be run as which is equal to main the module we specified and that will access the function cli in our main.py file

Now back in your terminal type this and press enter

pip install --editable .

We can now run our script with just the name.

You can add the options and or arguments the same way we did before.

A Practical Use for Click – Current Weather Program

We are going to build a program that gives us the current weather for an inputted city.

First, you have get an API key from OpenWeather, it’s free. You just have to sign up for an account.

The program consists of two parts:

  • One that makes a call to the API
  • Another – our click command – that passes the parameters to the API so that we get the weather information.

We will add to the last program as it already has some of the functionality we need. Modify it to look like this:

import requests
import click

# MAKING API CALL

SAMPLE_API_KEY = 'b1b15e88fa797225412429c1c50c122a1'

# function for current weather that takes location and api key
def current_weather(location, api_key=SAMPLE_API_KEY):
    url = 'https://api.openweathermap.org/data/2.5/weather'

    query_params = {
        'q': location,
        'appid': api_key,
    }

    # request to get api data
    response = requests.get(url, params=query_params)

    # check if response was 200 - successful
    if response.status_code == 200:
        # Return the json data for weather description
        return response.json()['weather'][0]['description']

        
# EXECUTING PROGRAM

@click.command()
# click argument for location which must be passed
@click.argument('location')
# click option for the api key
@click.option('--api-key', '-a', help='your API key for the OpenWeatherMap API',)
def cli(location, api_key):
    """
    A little weather tool that shows you the current weather in a LOCATION of
    your choice. Provide the city name and optionally a two-digit country code.
    """
    # invocation of current weather function
    weather = current_weather(location, api_key)
    click.echo(f"The weather in {location} right now: {weather}.")

if __name__ == "__main__":
    cli()

First, we write a function that will make a call to the Openweather API – this function will be called in our click module.

For the click part of our program, we will have an argument for location(city) and an option for the api key. In it we call our current_weather function.

We run our program like this:

[program name] [location] -a [api_key]
NOTE: You will have to use your own api key when you run this program

In this article we have introduced the click module. What it is and how we use it to build better CLIs. With it we have also added a better way to run our CLI. With that knowledge we have built a program that gives us the current weather.

Get Notified Automatically Of New Articles

Error SendFox Connection: 403 Forbidden

403 Forbidden