Building Rich Console Interfaces in Python

Martín Lamas
Trabe
Published in
6 min readSep 28, 2020
Photo by Cookie the Pom on Unsplash

Lately, I have been working on a project in which I needed to pretty print some data on the console. That was how I discovered Rich, a Python library for rich text and beautiful formatting in the terminal.

In this story I will show you some of the features of this library, and how you can use it in your projects.

Installing the library

First, we need to install the library in our environment using pip.

pip install rich

Once installed we can try some of the features of the library.

Rich text printing

One of the features that I use the most is to print rich text.

To do so, we must first import and build a Console object:

Now, we can style and print text on the console using the print method:

Console output of the previous example

In this example we can see that:

  • We can either style text fragments inline or style the whole text by passing the style keyword argument.
  • Inline styles are defined using strings. These strings contain keywords to set the colors and other attributes for the foreground styles (like bold white) and for the background color (on blue).
  • If we pass a hash to print it will be automatically styled.
  • We can print emojis using colon notation.

This is a list with the available attributes to define styles:

  • bold or b for bold text.
  • blink for text that flashes (use this one sparingly).
  • blink2 for text that flashes rapidly (not supported by most terminals).
  • conceal for concealed text (not supported by most terminals).
  • italic or i for italic text (not supported on Windows).
  • reverse or r for text with reversed foreground and background colors.
  • strike or s for text with a line through it.
  • underline or u for underlined text.

It also supports the following attributes, which are not universally supported and may not work on your terminal:

  • underline2 or uu for doubly underlined text.
  • frame for framed text.
  • encircle for encircled text.
  • overline or o for overlined text.

We can choose colors between one of the 256 Standard Colors. But we can also set a custom color using RGB codes. In the following example we print the same color using both its standard name and its RGB code:

Another useful feature of the library is the logger. We use this feature calling the log method on the Console instance. This method prints an output with three columns: the current time, the data to print and the file and line from which the call to log was made. As we have seen before, the library does pretty format Python structures and repr strings. If we log a collection (i.e. a dict or a list) the library pretty prints it so that it fits in the available terminal space.

Console output of the previous example

Tables

Another useful feature of the library is the ability to render tables on the terminal.

In the following example, we use the Table class to create a new table instance and then we call the add_column and add_row methods to define the table columns and add the data rows:

Console output of the table example

We define the table header style and the title passing the show_header, header_style and title keyword arguments in the constructor. For a headless table we have to set the keyword argument show_header to False and skip the others.

The column definition is performed by calling the add_column method. We simply call this method as many times as columns we want to create. We have to provide the title of the column and, optionally, the justification of the data cells (left, center or right).

Once the table structure is defined, we can insert a data row by calling the add_row method. We must pass the data as arguments in the same order the columns were defined. Each cell can be styled individually.

You can also change the default border using the box keyword in the Table constructor:

Console output of the table without borders

Progress bars

To track long-running tasks we can use a progress bar to improve the user experience. We need to import the track function to use the basic progress bar API. Then, we can wrap any sequence in this function and iterate over the result.

In this example, we iterate over a list of remote files in order to download them. Each iteration a file is downloaded and the progress bar is updated.

A progress bar. As expected

We can use the advanced API if we need to further customize our progress bar. In the following example we have a customized version of the example above:

In this example we first instantiate a Progress object to define the different columns that compose the progress bar: the task description, the bar, a live progress showing how many files have been downloaded and the remaining time.

Then, we add a task to the Progress instance using the add_task method passing the description and the total steps (the number of the files).

Finally, we iterate the file list and for each iteration we update the progress status by calling the update method.

An improved progress bar.

Markdown rendering

Another awesome Rich feature is markdown rendering.

Take the following markdown:

We can render it in the terminal with ease:

The formatted markdown output

Other useful features

There are other interesting functionalities of the library.

Columns

When we need to tabulate the data into columns we can create a Columns instance and pass the list of elements to tabulate in the constructor.

The following example shows how to render a directory content using columns:

We are using a helper function file_info to get the file info (name, type and file extension). We list the directory passed as command line argument and we wrap each found file into a Panel object to show the info inside a box. And, in turn, we put each panel inside a Columns object.

Files shown in columns

Syntax highlighting

Rich uses the pygments library under the hood to implement syntax highlighting. We can use this feature directly building a Syntax object:

Syntax highlighted Python code

Tracebacks

We can handle and print beautiful tracebacks in our programs. These tracebacks are easier to read and show more code than standard Python tracebacks.

Beautiful tracebacks

Summing up

Rich is a good choice to improve the user experience of our console applications. In this story we have learned how to use the most interesting features and how to apply them with some simple examples.

--

--