Beautiful CLIs With The Rich Python Library
Tags: beginners, python, 100daysofpython
Published: 2021-09-02 10:15:11

_**I write content for AWS, Kubernetes, Python, JavaScript and more. To view all the latest content, be sure to [visit my blog](https://blog.dennisokeeffe.com) and subscribe to my newsletter. [Follow me on Twitter](https://twitter.com/dennisokeeffe92).**_

> This is Day 13 of the #100DaysOfPython challenge.

This post will use the [rich](https://github.com/willmcgugan/rich) library to demonstrate how to add some color and formatting to your Python CLI output.

## Prerequisites

1. Familiarity with [Pipenv](https://pipenv.pypa.io/en/latest/). See [here](https://blog.dennisokeeffe.com/blog/2020-07-04-abcs-of-pipenv) for my post on Pipenv.
2. Read [Pretty errors in Python](https://blog.dennisokeeffe.com/blog/2021-07-30-pretty-error-output-in-python) for my post on how to make pretty error output in Python.
3. Read [CLI Prompts in Python](https://blog.dennisokeeffe.com/blog/2021-07-29-cli-prompts-in-python) for my post on how to make CLI prompts in Python.
4. Read [Building CLIs with python-fire](https://blog.dennisokeeffe.com/blog/2021-07-25-building-clis-with-python-fire) for my intro on building CLIs with `python-fire` that will be used today.
5. Familiarity with how [Python Fire](https://github.com/google/python-fire) works.

This works from the content of a previous post on [Pretty errors in Python](https://blog.dennisokeeffe.com/blog/2021-07-30-pretty-error-output-in-python).

While not necessary to understand the post, it is recommended that you read it if you are hoping to use the same code.

## Getting started

At this stage of the series, our code in `cli.py` for the project folder should look like the following:

```py
#!/usr/bin/env python
import fire
from PyInquirer import prompt
import pretty_errors


class IngestionStage(object):
    def run(self):
        return 'Ingesting! Nom nom nom...'


class DigestionStage(object):
    def __init__(self):
        self.satiated = False

    def run(self, volume: int) -> str:
        questions = [
            {
                'type': 'input',
                'name': 'volume',
                'message': 'How many burps?',
            }
        ]
        if volume == 0:
            volume = int(prompt(questions)['volume'])
        self.satiated = True
        return ' '.join(['Burp!'] * volume)

    def breakfast(self):
        questions = [
            {
                'type': 'list',
                'name': 'breakfast',
                'message': 'What did you want for breakfast?',
                'choices': ['eggs', 'bacon', 'toast']
            }
        ]
        switcher = {
            'eggs': 1,
            'bacon': 2,
            'toast': 3,
        }
        volume = switcher.get(prompt(questions)['breakfast'], 0)

        self.satiated = True
        return ' '.join(['Burp!'] * volume)

    def status(self):
        return 'Satiated.' if self.satiated else 'Not satiated.'


class Pipeline(object):

    def __init__(self):
        self.ingestion = IngestionStage()
        self.digestion = DigestionStage()

    def run(self, volume: int = 1):
        print(self.ingestion.run())
        print(self.digestion.run(volume=volume))
        print(self.digestion.status())
        return 'Pipeline complete'


if __name__ == '__main__':
    fire.Fire(Pipeline)
```

In today's post, we are hoping to just to show a demo of how easy it is to use `rich` to add some color to our output.

We can add the `rich` library to our current Pipenv environment by running the following command:

```s
# Add rich to dependencies
$ pipenv install rich
```

We are now ready to update our input.

## Adding color to our output

We will demo how rich works with simple example of adding color to the DigestionStage class method status.

Currently, the method looks like so:

```py
def status(self):
		return 'Satiated.' if self.satiated else 'Not satiated.'
```

Currently, if we run our the following commands in the terminal, we get output without color:

```s
$ python cli.py run --volume 2
Ingesting! Nom nom nom...
Burp! Burp!
Satiated.
Pipeline complete
$ python cli.py digestion status
Not satiated.
```

What we would like to do is to add some color to the output but updating the function to use the `print` function from the `rich` library and update what we return at the end.

We can do this with the following:

```py
# Top of the file
from rich import print

# ... code omitted for brevity

# Back at the `status` definition.
def status(self):
		print('[bold green]Satiated.[/bold green]') if self.satiated else print(
				'[bold red]Not satiated.[/bold red]')
		return 'Status complete'
```

Re-running the above commands will adjust the output slightly, but now `self.satiated` output printed in bold green when true and `self.satiated` output is printed in red when false.

```s
$ python cli.py run
Ingesting! Nom nom nom...
Burp!
Satiated.
Status complete
Pipeline complete
$ python cli.py digestion status
Not satiated.
Status complete
```

![Final output](https://cdn.dennisokeeffe.com/assets/2021-08-01-beautiful-clis-with-the-rich-python-library/1-final-output.png)

## Summary

Today's post demonstrated how to use the `rich` package to add some color to our output.

## Resources and further reading

1. [The ABCs of Pipenv](https://blog.dennisokeeffe.com/blog/2020-07-04-abcs-of-pipenv)
2. [Pipenv](https://pipenv.pypa.io/en/latest/)
3. [Pretty errors in Python](https://blog.dennisokeeffe.com/blog/2021-07-30-pretty-error-output-in-python)
4. [CLI Prompts in Python](https://blog.dennisokeeffe.com/blog/2021-07-29-cli-prompts-in-python)
5. [Building CLIs with python-fire](https://blog.dennisokeeffe.com/blog/2021-07-25-building-clis-with-python-fire)
6. [Python Fire](https://github.com/google/python-fire)
7. [rich](https://github.com/willmcgugan/rich)

_Photo credit: [`pawel_czerwinski`](https://unsplash.com/@pawel_czerwinski)_


_Originally posted on my [blog](https://blog.dennisokeeffe.com/blog/2021-08-01-beautiful-clis-with-the-rich-python-library). To see new posts without delay, read the posts there and subscribe to my newsletter._