Skip to content

Python Rich Library

Rich is a Python library for writing rich text (with color and style) to the terminal, and for displaying advanced content such as tables, markdown, and syntax highlighted code.

Use Rich to make your command line applications visually appealing and present data in a more readable way. Rich can also be a useful debugging aid by pretty printing and syntax highlighting data structures.

Rich can be installed with pip install rich.

Warning

This requires the following dependencies and has been tested at these specified versions:

requests==2.31.0
netutils==1.5.0
PyYAML==6.0.1
rich==13.5.2

Rich pprint (Pretty Print)

Rich's pprint has many more features than the pprint.pprint provided in standard library.

import requests
import yaml
from rich.pretty import pprint

# URL to the YAML file
url = "https://raw.githubusercontent.com/networktocode/ntc-templates/master/tests/cisco_ios/show_interfaces_status/cisco_ios_show_interfaces_status.yml"

# Fetch YAML data from the URL
response = requests.get(url)
yaml_data = response.text

# Parse YAML data
parsed_data = yaml.safe_load(yaml_data)["parsed_sample"]

pprint(parsed_data)

We can see how the pprint works with other object types,

data = {
    "integer": 10,
    "class": str,
    "string": "data",
    "None": None,
}

pprint(data)

pprint takes in multiple parameters, feel free to test them out.

  • max_string
  • max_depth
  • indent_guides
  • expand_all

Rich pprint (Pretty Print) - LAB

Go through the demo yourself, and test some of the options with this data or other data. Review the syntax for bbcode and test out those as well.

Console Markup

As per the documentation, console markup uses a syntax inspired by bbcode. The formatting has syntax like:

from rich.console import Console
console = Console()
console.print("[bold red]alert![/bold red] Something happened")
console.print("[bold italic yellow on red blink]This text is impossible to read")

Let's see this in action.

Formatting s

from rich.console import Console
console = Console()

for entry in parsed_data:
    name = entry["name"]
    port = entry["port"]
    speed = entry["speed"]
    status = entry["status"]

    # Apply italics to speed if "a-100"
    speed_text = speed if speed != "a-100" else f"[italic]{speed}[/italic]"

    # Determine color for status
    status_color = "green" if status == "connected" else "red"

    console.print(f"{name} - {port}: Speed: {speed_text} | Status: [{status_color}]{status}[/{status_color}]")

Console Markup - LAB

Go through the demo yourself, and review the syntax for bbcode and test those options as well.

Creating Tables

Let's observer the documentation on how to construct tables using Rich.

The primary components are:

  • Table Class
  • add_column method
  • add_row method

That is all you need to get started, but there are many options to control the styling of the table.

Let's see the table in action!

import requests
import yaml
from rich.console import Console
from rich.table import Table

# URL to the YAML file
url = "https://raw.githubusercontent.com/networktocode/ntc-templates/master/tests/cisco_ios/show_ip_route/cisco_ios_show_ip_route.yml"

# Fetch YAML data from the URL
response = requests.get(url)
yaml_data = response.text

# Parse YAML data
parsed_data = yaml.safe_load(yaml_data)["parsed_sample"]

# Create a rich table
console = Console()
table = Table(title="IP Route Information")
table.add_column("Network", style="bold")
table.add_column("Next Hop IP")
table.add_column("Protocol")
table.add_column("Interface")

# Populate the table with data
for entry in parsed_data:
    network = entry.get("network", "N/A")
    prefix_length = entry.get("prefix_length")
    nexthop_ip = entry.get("nexthop_ip", "N/A")
    protocol = entry.get("protocol", "N/A")
    nexthop_if = entry.get("nexthop_if", "N/A")
    table.add_row(f"{network}/{prefix_length}", nexthop_ip, protocol, nexthop_if)

# Display the table
console.print(table)

Let's modify to see some of the option that rich provides, as well as clean up the output a bit.

from rich.align import Align
from netutils.interface import abbreviated_interface_name

map_protocol = {
    "O": "OSPF",
    "C": "Connected",
    "i": "IS-IS",
    "D": "EIGRP",
    "S": "Static",
    "B": "BGP",
}

table = Table(title="IP Route Information")
table.add_column("Network", style="bold")
table.add_column("Next Hop IP")
table.add_column("Protocol")
table.add_column("Interface")

# Populate the table with data
for entry in parsed_data:
    network = entry.get("network", "N/A")
    prefix_length = entry.get("prefix_length")
    nexthop_ip = entry.get("nexthop_ip", "N/A")
    protocol = map_protocol[entry["protocol"]]
    if protocol == "Connected":
        protocol = "[bold magenta]Connected"
    nexthop_if = abbreviated_interface_name(entry.get("nexthop_if", "N/A"))
    table.add_row(f"{network}/{prefix_length}", nexthop_ip, Align(protocol, align="center"), nexthop_if)

console.print(table)

As you can see, you can update the color, alignment, and built a better user experience with modifying some of the returned output.

Rich Table - LAB

Develop a napalm script that uses the get_interfaces method and returns a table.

  • Provide the data that makes sense to show
  • Order in an intuitive manner
  • Stretch Goals
    • Update the UX to be as you would want it

Advanced Inputs

From the docs: "Rich has a number of Prompt classes which ask a user for input and loop until a valid response is received". These features provide greater capabilities over the Python builtin function input

Let's explore a few of those, in a file called rich_test.py.

from rich.console import Console
from rich.prompt import Prompt

username = Prompt.ask("Enter the username", choices=["cisco", "ntc", "admin"], default="cisco")
password = Prompt.ask("What password would you connect with", password=True)
device = Prompt.ask("Enter the device")

console = Console()
console.print(f"Netmiko: Connecting to [green]{device}[/green] with user [italic]{username}[/italic]")

Advanced Inputs - LAB

Go through the demo yourself and test out the various different ask method options .

Additional Features

Rich can be used to perform many other operations in Python, to name a few.

  • Trees - You can build an object oriented tree, that prints similar to the unix tree command.
  • Themes - The themes can be adjusted including color, font, etc.
  • Logger - There is an advanced logger that you can create.
  • Redirect - You can easily redirect stdout & stderr.
  • Progress bar - You can quickly create a progress bar with rich.
  • Dashboard layout - You can create a dashboard that splits horizontally, vertically, and provides many other features.