Back to Blog
Python

Python Rich Console: Print Tables and Panels

python rich console print tables and panels: Learn to render structured data as tables and panels in the Python console using Rich, with styling, alignment, and layout...

RichConsole OutputTerminal UIData TablesPanels
A terminal window displaying a Rich table and panel with styled columns and borders.

When you need to present structured data in a terminal, Python's Rich library provides a straightforward way to render tables and panels without manual string formatting. The Rich console can print tables with aligned columns, styled headers, and custom borders, and panels can group related content into visually distinct boxes. This article shows how to use python rich console print tables and panels effectively in your CLI tools and scripts.

Setting Up Rich and the Console

Rich is a third-party library, so you need to install it first. In most environments, pip install rich is enough. Once installed, you create a Console instance that handles output, styling, and terminal detection. The console object is the entry point for all rendering.

from rich.console import Console console = Console()

The Console automatically detects whether output is going to a terminal or being piped. This matters because Rich uses ANSI escape codes and Unicode box characters, which may not render correctly in all contexts. The console also respects environment variables like NO_COLOR and TERM to decide whether to emit styling.

Printing a Basic Table

The Table class is the core of structured output. You define columns and rows, then pass the table to console.print(). Here is a minimal example:

from rich.table import Table user_table = Table(title="Active Users") user_table.add_column("ID") user_table.add_column("Name") user_table.add_column("Email") user_table.add_row("1", "Alice", "alice@example.com") user_table.add_row("2", "Bob", "bob@example.com") console.print(user_table)

Rich automatically sizes columns based on content and terminal width. It also draws a border and header row by default. The title argument adds a centered title above the table. This basic usage covers most simple reporting needs.

Customizing Table Columns and Rows

You often need more control over alignment, width, and styling. Each column can have its own alignment, width, overflow behavior, and header style. For example, to right-align numeric IDs and limit the name column to 20 characters:

user_table.add_column("ID", justify="right", style="cyan") user_table.add_column("Name", width=20, overflow="fold") user_table.add_column("Email", justify="left")

The justify parameter accepts "left", "center", "right", or "full". width sets a fixed column width, and overflow controls what happens when content exceeds that width: "fold" wraps the text, "ellipsis" truncates with an ellipsis, and "crop" cuts off without an ellipsis. You can also style the header row separately with header_style.

Rows can be added with any number of cells, but they must match the number of columns. If a row has fewer cells, Rich leaves the remaining cells empty. You can also add rows with styles per cell using a rich.text.Text object, but for most cases plain strings are sufficient.

Using Panels for Grouping Content

Panels are boxes that surround a renderable, such as text, another table, or a combination of them. They are useful for highlighting a section of output or grouping related information. A panel takes a renderable as its first argument and supports a title, border style, and padding.

from rich.panel import Panel info_panel = Panel( "This is a simple panel.", title="Notice", border_style="bright_blue", padding=(1, 2) ) console.print(info_panel)

The padding argument is a tuple of (vertical, horizontal) padding in cells. Panels can contain any Rich renderable, including tables, making them a natural way to add context to tabular data.

Combining Tables and Panels

You can nest tables inside panels and vice versa. For example, to place a table inside a panel with a descriptive title:

inner_table = Table(title="Metrics") inner_table.add_column("Metric") inner_table.add_column("Value") inner_table.add_row("CPU", "42%") inner_table.add_row("Memory", "1.2 GB") wrapped = Panel(inner_table, title="System Status", border_style="green") console.print(wrapped)

Panels can also be placed inside table cells, though that is less common. When you embed a renderable inside a table cell, Rich will render it as a single block, which can be useful for creating complex layouts. However, keep in mind that table cells are sized based on the content, so nested panels may affect column widths.

Styling and Alignment Options

Rich provides a rich set of style options that apply to both tables and panels. You can set colors, bold, italic, underline, and more using style strings. For example, to make the header bold and the borders a specific color:

user_table.add_column("Name", header_style="bold magenta") user_table.border_style = "blue"

Panels accept border_style, title_align, and subtitle parameters. The title_align parameter controls where the title sits on the border: "left", "center", or "right". You can also use box to choose from different border styles, such as box.ROUNDED, box.SQUARE, or box.DOUBLE. For example:

from rich import box panel = Panel("Content", box=box.DOUBLE, title="Double Border")

Alignment inside a panel is handled by the renderable itself. If you want to center a paragraph, you can wrap it in a Text object with justify="center". This level of control lets you build polished terminal interfaces without relying on external tools.

Performance and Terminal Compatibility

Rich is designed for interactive terminals, but it also works when output is redirected. The main performance consideration is the overhead of building and styling renderables. For small to medium datasets, this is negligible. However, if you are printing thousands of rows, Rich will still construct the entire table in memory before rendering. This can be slow and memory-intensive. In such cases, consider limiting the number of rows or using a streaming approach with console.print on each row individually, though you lose the table formatting.

Terminal compatibility is another concern. Rich relies on Unicode box-drawing characters and ANSI escape codes. Most modern terminals support these, but older Windows consoles may require the Windows Terminal or enabling VT processing. Rich attempts to detect the terminal and falls back to a plain text representation when necessary. You can force this behavior by setting legacy_windows=True on the Console constructor, but it is rarely needed today.

For production tools, always test your output in the actual terminal environment. If you are piping output to a file or another program, consider using the record option or disabling styles with NO_COLOR to avoid embedding escape codes in logs.

python rich console print tables and panels: Practical Usage | RYUSLOG DEV