Tisk naformátovaného a obarveného textu na terminál s knihovnou Rich (dokončení)

22. 11. 2022
Doba čtení: 25 minut

Sdílet

 Autor: Depositphotos
Popíšeme si způsob zobrazení stromových struktur, jak se zobrazují tabulky s formátovaným textem, zobrazení dat umístěných do sloupců a v neposlední řadě si ukážeme například postupné zobrazení prováděné činnosti (progress bar).

Obsah

1. Zobrazení stromové struktury na ploše terminálu

2. Přidání uzlů do stromu metodou add, zobrazení celého stromu na terminálu

3. Přidání uzlů s poduzly do stromu

4. Specifikace barev textů v uzlech stromu

5. Volba, zda má být podstrom rozbalen či nikoli

6. Praktická ukázka použití stromu: zobrazení obsahu adresáře

7. Zobrazení průběhu výpočtu: progress bar

8. Progress bar vytvořený pro sekvenci

9. Výpočet prvočísel s vizualizací průběhu výpočtu

10. Využití instance třídy Progress ve funkci context manageru

11. Panely a sloupce

12. Změna stylu (barvy) textu umístěných do jednotlivých panelů, víceřádkový text

13. Automatické rozmístění patnácti panelů v rámci plochy terminálu

14. Zobrazení jednoduché tabulky

15. Formát textu v buňkách tabulky

16. Použití značky [bold] a [/bold] v buňkách tabulky

17. Zarovnání textu

18. Příloha: jména podporovaných barev

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Zobrazení stromové struktury na ploše terminálu

V úvodní části dnešního článku o knihovně Rich se seznámíme se zobrazením stromové struktury na ploše terminálu. Jedná se o poměrně často využívanou operaci, protože například systém souborů tvoří stromovou strukturu; ovšem může se jednat například i o vizualizaci struktury nějaké organizace, o strukturované poznámky, vizualizaci rozhodovacího stromu atd. atd. Pro zobrazení stromové struktury se používá třída nazvaná tree, kterou nalezneme v modulu rich.tree:

Help on class Tree in module rich.tree:
 
class Tree(rich.jupyter.JupyterMixin)
 |  Tree(label: Union[rich.console.ConsoleRenderable, rich.console.RichCast, str], *, style: Union[str, ForwardRef('Style')] = 'tree', guide_style: Union[str, ForwardRef('Style')] = 'tree.line', expanded: bool = True, highlight: bool = False, hide_root: bool = False) -> None
 |
 |  A renderable for a tree structure.
 |
 |  Args:
 |      label (RenderableType): The renderable or str for the tree label.
 |      style (StyleType, optional): Style of this tree. Defaults to "tree".
 |      guide_style (StyleType, optional): Style of the guide lines. Defaults to "tree.line".
 |      expanded (bool, optional): Also display children. Defaults to True.
 |      highlight (bool, optional): Highlight renderable (if str). Defaults to False.
 |
 |  Method resolution order:
 |      Tree
 |      rich.jupyter.JupyterMixin
 |      builtins.object

Samozřejmě můžeme pro zobrazení informací o třídě Tree využít i metodu inspect, kterou jsme si popsali minule:

from rich import inspect
from rich.tree import Tree
 
inspect(Tree, methods=True)

Výsledek zobrazený na textovém terminálu může vypadat následovně:

Obrázek 1: Základní informace o třídě Tree zobrazené funkcí inspect.

2. Přidání uzlů do stromu metodou add, zobrazení celého stromu na terminálu

Po konstrukci instance třídy Tree můžeme do takto vytvořeného uzlu přidávat uzly (a popř. celé podstromy) metodou add. V tom nejjednodušším případě postačuje této metodě předat pouze text, kterým je uzel stromu popsán. Pro ilustraci se pokusme o vytvoření stromu s pěti uzly (na stejné úrovni). Samotný kořen stromu je taktéž popsán textem. Strom lze vykreslit upravenou funkcí print:

from rich.tree import Tree
from rich import print
 
 
tree = Tree("Barvové modely")
tree.add("RGB")
tree.add("CMYK")
tree.add("YUV")
tree.add("HSL")
tree.add("HSV")
 
print(tree)

Výsledek bude vypadat takto:

Obrázek 2: Jednoúrovňový strom s kořenem a pěti uzly.

Zobrazme si navíc informace o samotné instanci třídy Tree. K tomuto účelu opět použijeme funkci inspect, kterou již dobře známe:

from rich import inspect
from rich.tree import Tree
 
tree = Tree("Barvové modely")
tree.add("RGB")
tree.add("CMYK")
tree.add("YUV")
tree.add("HSL")
tree.add("HSV")
 
inspect(tree, methods=True)

S výsledkem:

Obrázek 3: Informace o instanci třídy Tree zobrazené funkcí inspect.

3. Přidání uzlů s poduzly do stromu

Uzel, který je vložený do stromu (tedy do instance třídy Tree) metodou add, je opět instancí třídy Tree. O tom se přesvědčíme triviálním způsobem:

from rich import inspect
from rich.tree import Tree
 
tree = Tree("Strom")
node = tree.add("Uzel")
 
inspect(node)

S tímto výsledkem:

Obrázek 4: Informace o uzlu zobrazené funkcí inspect.

To tedy znamená, že můžeme vytvořit strom, jehož uzly budou obsahovat další poduzly. V případě jediného poduzlu lze použít tento trik:

from rich.tree import Tree
from rich import print
 
 
tree = Tree("Barvové modely")
tree.add("RGB").add("Red Green Blue")
tree.add("CMYK").add("Cyan Magenta Yellow blacK")
tree.add("YUV").add("Luminance Chrominance")
tree.add("HSL").add("Hue Saturation Lightness")
tree.add("HSV").add("Hue Saturation Value")
 
print(tree)

Výsledný strom bude vypadat takto:

Obrázek 5: Strom s pěti uzly, z nichž každý obsahuje jediný poduzel.

V případě, že má nějaký uzel stromu obsahovat větší množství poduzlů, vypomůžeme si použitím proměnných, z nichž každá bude obsahovat daný podstrom:

from rich.tree import Tree
from rich import print
 
 
tree = Tree("Barvové modely")
rgb = tree.add("RGB")
cmyk = tree.add("CMYK")
yuv = tree.add("YUV")
hsl = tree.add("HSL")
hsv = tree.add("HSV")
 
rgb.add("Red")
rgb.add("Green")
rgb.add("Blue")
 
cmyk.add("Cyan")
cmyk.add("Magenta")
cmyk.add("Yellow")
cmyk.add("blacK")
 
hsl.add("Hue")
hsl.add("Saturation")
hsl.add("Lightness")
 
hsv.add("Hue")
hsv.add("Saturation")
hsv.add("Value")
 
print(tree)

Opět se podívejme na výsledek:

Obrázek 6: Strom s pěti uzly, které mohou obsahovat další poduzly.

4. Specifikace barev textů v uzlech stromu

Struktura resp. struktury zobrazené ve stromu nebyly zvoleny náhodně, neboť některé uzly obsahují jména barev. Uzly stromu totiž skutečně můžeme obarvit, a to takovým způsobem, že jméno barvy zapíšeme do hranatých závorek. Ostatně vše bude patrné z následujícího příkladu:

from rich.tree import Tree
from rich import print
 
 
tree = Tree("Barvové modely")
rgb = tree.add("RGB")
cmyk = tree.add("CMYK")
yuv = tree.add("YUV")
hsl = tree.add("HSL")
hsv = tree.add("HSV")
 
rgb.add("[red]Red")
rgb.add("[green]Green")
rgb.add("[blue]Blue")
 
cmyk.add("[cyan]Cyan")
cmyk.add("[magenta]Magenta")
cmyk.add("[yellow]Yellow")
cmyk.add("[black]blacK")
 
hsl.add("Hue")
hsl.add("Saturation")
hsl.add("Lightness")
 
hsv.add("Hue")
hsv.add("Saturation")
hsv.add("Value")
 
print(tree)

Podívejme se na výsledek (včetně poněkud nešťastně zvolené černé barvy):

Obrázek 7: Strom s pěti uzly, které mohou obsahovat další poduzly. Některé poduzly jsou obarveny.

Obarveny však nejsou celé uzly, pouze text za jménem barvy. O tom se opět můžeme velmi snadno přesvědčit:

from rich.tree import Tree
from rich import print
 
 
tree = Tree("Barvové modely")
rgb = tree.add("RGB")
cmyk = tree.add("CMYK")
yuv = tree.add("YUV")
hsl = tree.add("HSL")
hsv = tree.add("HSV")
 
rgb.add("barva [red]Red")
rgb.add("barva [green]Green")
rgb.add("barva [blue]Blue")
 
cmyk.add("barva [cyan]Cyan")
cmyk.add("barva [magenta]Magenta")
cmyk.add("barva [yellow]Yellow")
cmyk.add("barva [black]blacK")
 
hsl.add("Hue")
hsl.add("Saturation")
hsl.add("Lightness")
 
hsv.add("Hue")
hsv.add("Saturation")
hsv.add("Value")
 
print(tree)

Na terminál se v tomto případě vykreslí tento strom:

Obrázek 8: Strom s pěti uzly, které mohou obsahovat další poduzly. Některé poduzly jsou částečně obarveny.

5. Volba, zda má být podstrom rozbalen či nikoli

Nepovinným parametrem expanded nastaveným na pravdivostní hodnotu True či False je možné určit, jestli se má zvolený (právě vytvářený) podstrom daného uzlu zobrazit v rozbalené podobně či nikoli. V dalším demonstračním příkladu je tato volba použita u podstromu CMYK:

from rich.tree import Tree
from rich import print
 
 
tree = Tree("Barvové modely")
rgb = tree.add("RGB")
cmyk = tree.add("CMYK", expanded=False)
yuv = tree.add("YUV")
hsl = tree.add("HSL")
hsv = tree.add("HSV")
 
rgb.add("barva [red]Red")
rgb.add("barva [green]Green")
rgb.add("barva [blue]Blue")
 
cmyk.add("barva [cyan]Cyan")
cmyk.add("barva [magenta]Magenta")
cmyk.add("barva [yellow]Yellow")
cmyk.add("barva [black]blacK")
 
hsl.add("Hue")
hsl.add("Saturation")
hsl.add("Lightness")
 
hsv.add("Hue")
hsv.add("Saturation")
hsv.add("Value")
 
print(tree)

S výsledkem:

Obrázek 9: Uzel CMYK sice obsahuje poduzly, ty však nejsou zobrazeny (podstrom je zabalený).

6. Praktická ukázka použití stromu: zobrazení obsahu adresáře

Na adrese https://github.com/Textua­lize/rich/blob/master/exam­ples/tree.py naleznete skript, který po svém spuštění vytiskne strom s vizualizací obsahu zvoleného adresáře. Povšimněte si, že se zobrazují (přes Unicode) i ikony u známých typů souborů:

"""
Demonstrates how to display a tree of files / directories with the Tree renderable.
"""
 
import os
import pathlib
import sys
 
from rich import print
from rich.filesize import decimal
from rich.markup import escape
from rich.text import Text
from rich.tree import Tree
 
 
def walk_directory(directory: pathlib.Path, tree: Tree) -> None:
    """Recursively build a Tree with directory contents."""
    # Sort dirs first then by filename
    paths = sorted(
        pathlib.Path(directory).iterdir(),
        key=lambda path: (path.is_file(), path.name.lower()),
    )
    for path in paths:
        # Remove hidden files
        if path.name.startswith("."):
            continue
        if path.is_dir():
            style = "dim" if path.name.startswith("__") else ""
            branch = tree.add(
                f"[bold magenta]:open_file_folder: [link file://{path}]{escape(path.name)}",
                style=style,
                guide_style=style,
            )
            walk_directory(path, branch)
        else:
            text_filename = Text(path.name, "green")
            text_filename.highlight_regex(r"\..*$", "bold red")
            text_filename.stylize(f"link file://{path}")
            file_size = path.stat().st_size
            text_filename.append(f" ({decimal(file_size)})", "blue")
            icon = "🐍 " if path.suffix == ".py" else "📄 "
            tree.add(Text(icon) + text_filename)
 
 
try:
    directory = os.path.abspath(sys.argv[1])
except IndexError:
    print("[b]Usage:[/] python tree.py <DIRECTORY>")
else:
    tree = Tree(
        f":open_file_folder: [link file://{directory}]{directory}",
        guide_style="bold bright_blue",
    )
    walk_directory(pathlib.Path(directory), tree)
    print(tree)

Podívejme se nyní na ukázky výstupu:

Obrázek 10: Zobrazení obsahu adresáře (výřez výstupu).

Obrázek 11: Zobrazení obsahu adresáře (výřez výstupu).

7. Zobrazení průběhu výpočtu: progress bar

V případě, že se provádí nějaký zdlouhavý výpočet nebo zpracování dat a současně je alespoň zhruba známý počet kroků nutných k dokončení této činnosti, můžeme uživatele o průběhu výpočtu informovat s využitím klasického „teploměru“ (progress bar). Jedná se o objekt, který se vytváří (a současně i zobrazí) funkcí track:

Help on function track in module rich.progress:
 
track(sequence: Union[Sequence[~ProgressType], Iterable[~ProgressType]], description: str = 'Working...', total: Union[float, NoneType] = None, auto_refresh: bool = True, console: Union[rich.console.Console, NoneType] = None, transient: bool = False, get_time: Union[Callable[[], float], NoneType] = None, refresh_per_second: float = 10, style: Union[str, ForwardRef('Style')] = 'bar.back', complete_style: Union[str, ForwardRef('Style')] = 'bar.complete', finished_style: Union[str, ForwardRef('Style')] = 'bar.finished', pulse_style: Union[str, ForwardRef('Style')] = 'bar.pulse', update_period: float = 0.1, disable: bool = False, show_speed: bool = True) -> Iterable[~ProgressType]
    Track progress by iterating over a sequence.
 
    Args:
        sequence (Iterable[ProgressType]): A sequence (must support "len") you wish to iterate over.
        description (str, optional): Description of task show next to progress bar. Defaults to "Working".
        total: (float, optional): Total number of steps. Default is len(sequence).
        auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True.
        transient: (bool, optional): Clear the progress on exit. Defaults to False.
        console (Console, optional): Console to write to. Default creates internal Console instance.
        refresh_per_second (float): Number of times per second to refresh the progress information. Defaults to 10.
        style (StyleType, optional): Style for the bar background. Defaults to "bar.back".
        complete_style (StyleType, optional): Style for the completed bar. Defaults to "bar.complete".
        finished_style (StyleType, optional): Style for a finished bar. Defaults to "bar.finished".
        pulse_style (StyleType, optional): Style for pulsing bars. Defaults to "bar.pulse".
        update_period (float, optional): Minimum time (in seconds) between calls to update(). Defaults to 0.1.
        disable (bool, optional): Disable display of progress.
        show_speed (bool, optional): Show speed if total isn't known. Defaults to True.
    Returns:
        Iterable[ProgressType]: An iterable of the values in the sequence.

8. Progress bar vytvořený pro sekvenci

Důležitý je především parametr sequence, kterým může být libovolná sekvence (například vytvořená pomocí range), přes níž se iteruje a z níž lze odvodit, jak dlouho bude výpočet prováděn. Ostatně si to ukažme na demonstračním příkladu získaném z originální dokumentace, který ukazuje, jak lze iterovat přes hodnoty 0 až 100 (vždy se zpožděním 0.02 sekundy)

from rich.progress import track
from time import sleep
 
 
def process_data():
    sleep(0.02)
 
 
for _ in track(range(100), description='[green]Processing data'):
    process_data()

Podívejme se na výsledky, konkrétně na terminál na začátku výpočtu a na konci výpočtu:

Obrázek 12: Zobrazení průběhu výpočtu: začátek výpočtu.

Obrázek 13: Zobrazení průběhu výpočtu: dokončení výpočtu.

9. Výpočet prvočísel s vizualizací průběhu výpočtu

Podívejme se nyní na poněkud praktičtější příklad. Bude se jednat o relativně pomalý algoritmus určený pro výpočet prvočísel. Vzhledem k tomu, že výpočet může být pro větší limit pomalý, budeme na terminál zobrazovat i průběh výpočtu s využitím progress baru. Jediná změna, kterou bylo nutné realizovat, je ve zdrojovém kódu zvýrazněna:

from rich.progress import track
 
# originální kód lze nalézt na adrese:
# http://www.rosettacode.org/wiki/Sieve_of_Eratosthenes#Using_array_lookup
def primes2(limit):
    """Výpočet seznamu prvočísel až do zadaného limitu."""
    is_prime = [False] * 2 + [True] * (limit - 1)
    for n in track(range(int(limit ** 0.5 + 1.5))):
        if is_prime[n]:
            for i in range(n * n, limit + 1, n):
                is_prime[i] = False
    return [i for i, prime in enumerate(is_prime) if prime]
 
 
print(primes2(100))

Obrázek 14: Výpočet prvočísel s postupnou změnou progress baru.

10. Využití instance třídy Progress ve funkci context manageru

Třída Progress, resp. přesněji řečeno instance této třídy, lze využít i ve funkci context manageru, tedy (zjednodušeně řečeno) v programové konstrukci with. V následujícím příkladu nejdříve vytvoříme dva ukazatele průběhu s maximální hodnotou nastavenou na 100. Následně ve smyčce postupně zvyšujeme interní hodnotu každého ukazatele průběhu o 0,3 resp. 0,2, přičemž díky použití context manageru je zaručeno, že je smyčka ukončena až tehdy, když oba interní čítače dosáhnou či přesáhnou hodnoty 100:

from rich.progress import Progress
import time
 
with Progress() as progress_bars:
 
    task1 = progress_bars.add_task("[blue]Task #1...", total=100)
    task2 = progress_bars.add_task("[yellow]Task #2...", total=100)
 
    while not progress_bars.finished:
        progress_bars.update(task1, advance=0.3)
        progress_bars.update(task2, advance=0.2)
        time.sleep(0.01)

Obrázek 15: Dva paralelně běžící ukazatele průběhu.

Podívat se můžeme i na zpomalený „progress“ u většího množství úloh, zde konkrétně u čtveřice úloh:

from rich.progress import Progress
import time
 
with Progress() as progress_bars:
 
    task1 = progress_bars.add_task("[blue]Task #1...", total=100)
    task2 = progress_bars.add_task("[yellow]Task #2...", total=100)
    task3 = progress_bars.add_task("[red]Task #3...", total=100)
    task4 = progress_bars.add_task("[green]Task #4...", total=100)
 
    while not progress_bars.finished:
        progress_bars.update(task1, advance=0.3)
        progress_bars.update(task2, advance=0.2)
        progress_bars.update(task3, advance=0.1)
        progress_bars.update(task4, advance=0.05)
        time.sleep(0.01)

Obrázek 16: Čtyři paralelně běžící ukazatele průběhu.

11. Panely a sloupce

Poměrně často se setkáme s nutností zobrazit větší množství různých „kartiček“ (resp. panelů) na ploše terminálu, přičemž ovšem není dopředu zřejmé, jak široké tyto kartičky budou a především není jasné, jak široká je vlastně plocha terminálu (zde pochopitelně měřená ve znacích a nikoli v pixelech). Na druhou stranu ovšem nechceme, aby byly kartičky/panely na ploše terminálu rozmístěny zcela náhodně; ideální by bylo rozmístění do dynamicky vytvořených sloupců, přičemž dopředu neznáme počet sloupců ani jejich šířku. A přesně k tomuto účelu slouží v knihovně Rich třídy Panel a Columns, přičemž panely mohou obsahovat textové objekty a jsou umístěny do sloupců (nicméně sloupce se spíše podobají konceptu gridu a nikoli tabulkám, protože jejich počet se dynamicky mění). Podívejme se na jednoduchý demonstrační příklad se třemi panely:

from rich.console import Console
from rich.columns import Columns
from rich.panel import Panel
 
 
console = Console()
 
panel1 = Panel("První")
panel2 = Panel("Druhý")
panel3 = Panel("Třetí")
 
columns = Columns([panel1, panel2, panel3])
console.print(columns)

Zajímavé bude otestovat si chování tohoto skriptu při změně šířky terminálu:

Obrázek 17: Zobrazení tří panelů na dostatečně širokém terminálu.

Obrázek 18: Zobrazení tří panelů na úzkém terminálu.

Obrázek 19: Zobrazení tří panelů na ještě užším terminálu.

12. Změna stylu (barvy) textu umístěných do jednotlivých panelů, víceřádkový text

Do panelů, které jsou rozmisťovány do automaticky vypočtených sloupců, lze umístit víceřádkový text – postačuje použít řídicí znak \n. Navíc je možné, aby byl tento text obarvený, přičemž barva (části) textu se zapisuje značkou [barva], což je styl, který jsme mohli vidět již při práci se stromy v úvodních kapitolách. Podívejme se tedy na způsob zápisu několika panelů s popisky barvových modelů (opět se tedy vracíme k již výše zmíněným demonstračním příkladům):

from rich.console import Console
from rich.columns import Columns
from rich.panel import Panel
 
 
console = Console()
 
panel1 = Panel("RGB\n\n[red]Red\n[green]Green\n[blue]Blue")
panel2 = Panel("CMYK\n\n[cyan]Cyan\n[magenta]Magenta\n[yellow]Yellow\n[black]blacK")
panel3 = Panel("YUV")
panel4 = Panel("HSL\n\nHue\nSaturation\nLightness")
panel5 = Panel("HSV\n\nHua\nSaturation\nValue")
 
columns = Columns([panel1, panel2, panel3, panel4, panel5])
console.print(columns)

Nyní by měl výsledek (pochopitelně na dostatečně širokém terminálu) vypadat následovně:

Obrázek 20: Víceřádkový a obarvený text umístěný do jednotlivých panelů, které jsou rozmístěny do dynamicky spočtených sloupců.

13. Automatické rozmístění patnácti panelů v rámci plochy terminálu

Nepatrnou úpravou příkladu z předchozí kapitoly, konkrétně přidáním operace pro opakování seznamu (viz zvýrazněnou část), si můžeme otestovat, jak vlastně bude vypadat plocha terminálu po zobrazení patnácti panelů a nikoli pouze tří panelů:

from rich.console import Console
from rich.columns import Columns
from rich.panel import Panel
 
 
console = Console()
 
panel1 = Panel("RGB\n\n[red]Red\n[green]Green\n[blue]Blue")
panel2 = Panel("CMYK\n\n[cyan]Cyan\n[magenta]Magenta\n[yellow]Yellow\n[black]blacK")
panel3 = Panel("YUV")
panel4 = Panel("HSL\n\nHue\nSaturation\nLightness")
panel5 = Panel("HSV\n\nHua\nSaturation\nValue")
 
columns = Columns([panel1, panel2, panel3, panel4, panel5]*5)
console.print(columns)

Opět se podívejme na výsledky získané po spuštění tohoto demonstračního příkladu na dvou terminálech s rozdílnou velikostí plochy:

Obrázek 21: Zobrazení patnácti panelů na širokém terminálu.

Obrázek 22: Zobrazení patnácti panelů na užším terminálu.

14. Zobrazení jednoduché tabulky

Poslední užitečnou vlastností knihovny Rich, kterou si dnes alespoň ve stručnosti popíšeme, je podpora pro zobrazení tabulek. Samotná tabulka je reprezentována objektem typu Table (což asi není příliš překvapivé). Pro tabulku lze deklarovat titulky a popř. i styly sloupců, a to metodou Table.add_column. Dále lze do tabulky přidávat jednotlivé řádky metodou Table.add_row. Podívejme se nyní na velmi jednoduchý příklad s tabulkou, která bude mít dva sloupce a čtyři řádky:

from rich.console import Console
from rich.table import Table
 
table = Table(title="Barvové modely")
 
table.add_column("Zkratka")
table.add_column("Význam")
 
table.add_row("RGB", "Red Green Blue")
table.add_row("CMYK", "Cyan Magenta Yellow blacK")
table.add_row("HSL", "Hue Saturation Lightness")
table.add_row("HSV", "Hue Saturation Value")
 
console = Console()
console.print(table)

Výsledkem činnosti tohoto skriptu bude následující tabulka:

Obrázek 23: Zobrazení jednoduché tabulky se dvěma sloupci a čtyřmi řádky.

15. Formát textu v buňkách tabulky

Text, který je zapsán do buněk tabulky, je pochopitelně možné různým způsobem formátovat. Opět se podívejme na způsob použití značek pro specifikaci barev textu. Povšimněte si, že každá další zapsaná značka ruší (podle očekávání) význam značky předchozí (není tedy striktně nutné značky uzavírat):

from rich.console import Console
from rich.table import Table
 
table = Table(title="Barvové modely")
 
table.add_column("Zkratka")
table.add_column("Význam")
table.add_column("Komponenty")
 
table.add_row("RGB", "Red Green Blue", "[red]Red [green]Green [blue]Blue")
table.add_row("CMYK", "Cyan Magenta Yellow blacK", "[cyan]Cyan [magenta]Magenta [yellow]Yellow [black]blacK")
table.add_row("HSL", "Hue Saturation Lightness", "")
table.add_row("HSV", "Hue Saturation Value", "")
 
console = Console()
console.print(table)

Podívejme se na výsledek:

Obrázek 24: Zobrazení jednoduché tabulky se třemi sloupci a čtyřmi řádky, přičemž část textu jsou zobrazeny barevně.

16. Použití značky [bold] a [/bold] v buňkách tabulky

Demonstrační příklad z předchozí kapitoly lze vylepšit takovým způsobem, že se zvýrazní ta písmena, ze kterých se skládá zkratka barvového modelu. Pro tento účel použijeme značku [bold] a vzhledem k tomu, že budeme chtít zvýraznit vždy jen jediný znak, budeme muset použít i uzavírací značku [/bold], tedy použije se prakticky totožný zápis, jaký je známý z HTML (až na odlišné znaky pro zápis samotných značek):

from rich.console import Console
from rich.table import Table
 
table = Table(title="Barvové modely")
 
table.add_column("Zkratka")
table.add_column("Význam")
table.add_column("Komponenty")
 
table.add_row("RGB", "[bold]R[/bold]ed [bold]G[/bold]reen [bold]B[/bold]lue", "[red]Red [green]Green [blue]Blue")
table.add_row("CMYK", "[bold]C[/bold]yan [bold]M[/bold]agenta [bold]Y[/bold]ellow blac[bold]K[/bold]", "[cyan]Cyan [magenta]Magenta [yellow]Yellow [black]blacK")
table.add_row("HSL", "[bold]H[/bold]ue [bold]S[/bold]aturation [bold]L[/bold]ightness", "")
table.add_row("HSV", "[bold]H[/bold]ue [bold]S[/bold]aturation [bold]V[/bold]alue", "")
 
console = Console()
console.print(table)

Výsledek:

Obrázek 25: Zobrazení jednoduché tabulky se třemi sloupci a čtyřmi řádky, přičemž část textu jsou zobrazeny barevně. Tučně jsou navíc zvýrazněny ty znaky, z nichž se skládá zkratka názvu barvového modelu.

17. Zarovnání textu

V dnešním posledním demonstračním příkladu je ukázán způsob zobrazení dlouhého odstavce, jehož text se nevejde na jediný řádek. Takový odstavec může být zarovnán doleva, doprava, na střed (vycentrován) nebo zarovnán na oba okraje:

from rich.console import Console, Text
 
paragraph = Text(
    """\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n"""
)
 
console = Console()
 
console.rule("justify='left'")
console.print(paragraph, style="red")
console.print()
 
console.rule("justify='center'")
console.print(paragraph, style="green", justify="center")
console.print()
 
console.rule("justify='right'")
console.print(paragraph, style="blue", justify="right")
console.print()
 
console.rule("justify='full'")
console.print(paragraph, style="magenta", justify="full")
console.print()

S tímto výsledkem:

Obrázek 26: Odstavec, který je postupně zarovnán doleva, na střed, doprava a nakonec na oba okraje.

bitcoin školení listopad 24

18. Příloha: jména podporovaných barev

V této příloze jsou vypsána jména všech barev, která je možné použít v hranatých závorkách pro ovlivnění barvy textu v terminálu (například uzlu stromu atd.):

black
red
green
yellow
blue
magenta
cyan
white
bright_black
bright_red
bright_green
bright_yellow
bright_blue
bright_magenta
bright_cyan
bright_white
grey0
gray0
navy_blue
dark_blue
blue3
blue1
dark_green
deep_sky_blue4
dodger_blue3
dodger_blue2
green4
spring_green4
turquoise4
deep_sky_blue3
dodger_blue1
green3
spring_green3
dark_cyan
light_sea_green
deep_sky_blue2
deep_sky_blue1
spring_green2
cyan3
dark_turquoise
turquoise2
green1
spring_green1
medium_spring_green
cyan2
cyan1
dark_red
deep_pink4
purple4
purple3
blue_violet
orange4
grey37
gray37
medium_purple4
slate_blue3
royal_blue1
chartreuse4
dark_sea_green4
pale_turquoise4
steel_blue
steel_blue3
cornflower_blue
chartreuse3
cadet_blue
sky_blue3
steel_blue1
pale_green3
sea_green3
aquamarine3
medium_turquoise
chartreuse2
sea_green2
sea_green1
aquamarine1
dark_slate_gray2
dark_magenta
dark_violet
purple
light_pink4
plum4
medium_purple3
slate_blue1
yellow4
wheat4
grey53
gray53
light_slate_grey
light_slate_gray
medium_purple
light_slate_blue
dark_olive_green3
dark_sea_green
light_sky_blue3
sky_blue2
dark_sea_green3
dark_slate_gray3
sky_blue1
chartreuse1
light_green
pale_green1
dark_slate_gray1
red3
medium_violet_red
magenta3
dark_orange3
indian_red
hot_pink3
medium_orchid3
medium_orchid
medium_purple2
dark_goldenrod
light_salmon3
rosy_brown
grey63
gray63
medium_purple1
gold3
dark_khaki
navajo_white3
grey69
gray69
light_steel_blue3
light_steel_blue
yellow3
dark_sea_green2
light_cyan3
light_sky_blue1
green_yellow
dark_olive_green2
dark_sea_green1
pale_turquoise1
deep_pink3
magenta2
hot_pink2
orchid
medium_orchid1
orange3
light_pink3
pink3
plum3
violet
light_goldenrod3
tan
misty_rose3
thistle3
plum2
khaki3
light_goldenrod2
light_yellow3
grey84
gray84
light_steel_blue1
yellow2
dark_olive_green1
honeydew2
light_cyan1
red1
deep_pink2
deep_pink1
magenta1
orange_red1
indian_red1
hot_pink
dark_orange
salmon1
light_coral
pale_violet_red1
orchid2
orchid1
orange1
sandy_brown
light_salmon1
light_pink1
pink1
plum1
gold1
navajo_white1
misty_rose1
thistle1
yellow1
light_goldenrod1
khaki1
wheat1
cornsilk1
grey100
gray100
grey3
gray3
grey7
gray7
grey11
gray11
grey15
gray15
grey19
gray19
grey23
gray23
grey27
gray27
grey30
gray30
grey35
gray35
grey39
gray39
grey42
gray42
grey46
gray46
grey50
gray50
grey54
gray54
grey58
gray58
grey62
gray62
grey66
gray66
grey70
gray70
grey74
gray74
grey78
gray78
grey82
gray82
grey85
gray85
grey89
gray89
grey93
gray93

19. Repositář s demonstračními příklady

Zdrojové kódy všech minule i dnes popsaných demonstračních příkladů určených pro Python 3 byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Jméno souboru Stručný popis souboru Cesta
1 standard_print.py chování standardní funkce print https://github.com/tisnik/most-popular-python-libs/blob/master/rich/stan­dard_print.py
2 rich_print1.py první způsob importu a volání vylepšené varianty funkce print https://github.com/tisnik/most-popular-python-libs/blob/master/rich/rich_print1.py
3 rich_print2.py druhý způsob importu a volání vylepšené varianty funkce print https://github.com/tisnik/most-popular-python-libs/blob/master/rich/rich_print2.py
4 rich_print3.py třetí způsob importu a volání vylepšené varianty funkce print https://github.com/tisnik/most-popular-python-libs/blob/master/rich/rich_print3.py
5 console_log1.py zobrazení zvolené hodnoty na konzoli https://github.com/tisnik/most-popular-python-libs/blob/master/rich/console_log1.py
6 console_log2.py zobrazení zvolené hodnoty i lokálních proměnných na konzoli https://github.com/tisnik/most-popular-python-libs/blob/master/rich/console_log2.py
7 console_log3.py způsob práce s časovým razítkem https://github.com/tisnik/most-popular-python-libs/blob/master/rich/console_log3.py
8 console_json1.py tisk hodnot na konzoli ve formátu JSON https://github.com/tisnik/most-popular-python-libs/blob/master/rich/console_json1.py
9 console_json2.py tisk všech lokálních proměnných na konzoli ve formátu JSON https://github.com/tisnik/most-popular-python-libs/blob/master/rich/console_json2.py
10 inspect1.py funkce inspect a třída list https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect1.py
11 inspect2.py funkce inspect; tisk všech viditelných metod třídy/objektu https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect2.py
12 inspect3.py funkce inspect; tisk všech metod i atributů třídy/objektu https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect3.py
13 inspect4.py funkce inspect; tisk instance třídy Queue https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect4.py
14 inspect5.py funkce inspect; tisk všech metod instance třídy Queue https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect5.py
15 inspect6.py funkce inspect; tisk všech privátních metod instance třídy Queue https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect6.py
16 inspect7.py funkce inspect; tisk všech atributů i metod instance třídy Queue https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect7.py
17 queue_print.py tisk informací o frontě standardní funkcí print https://github.com/tisnik/most-popular-python-libs/blob/master/rich/queue_print.py
       
18 inspect_tree1.py veřejné atributy a metody třídy Tree https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect_tree1.py
19 inspect_tree2.py veřejné atributy a metody instance třídy Tree https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect_tree2.py
20 inspect_tree3.py uzel stromu je opět instancí třídy Tree https://github.com/tisnik/most-popular-python-libs/blob/master/rich/inspect_tree3.py
       
21 tree1.py konstrukce a zobrazení stromové struktury https://github.com/tisnik/most-popular-python-libs/blob/master/rich/tree1.py
22 tree2.py strom, jehož uzly obsahují poduzly https://github.com/tisnik/most-popular-python-libs/blob/master/rich/tree2.py
23 tree3.py rozvětvený strom https://github.com/tisnik/most-popular-python-libs/blob/master/rich/tree3.py
24 tree4.py nastavení barev jednotlivých uzlů https://github.com/tisnik/most-popular-python-libs/blob/master/rich/tree4.py
25 tree5.py nastavení barev jednotlivých uzlů https://github.com/tisnik/most-popular-python-libs/blob/master/rich/tree5.py
26 tree6.py nastavení vlastností jednotlivých uzlů https://github.com/tisnik/most-popular-python-libs/blob/master/rich/tree6.py
       
27 progress_bar1.py progress bar (zobrazení průběhu výpočtu) https://github.com/tisnik/most-popular-python-libs/blob/master/rich/progress_bar1.py
28 progress_bar2.py progress bar (zobrazení průběhu výpočtu prvočísel) https://github.com/tisnik/most-popular-python-libs/blob/master/rich/progress_bar2.py
29 progress_bar3.py několik progress barů https://github.com/tisnik/most-popular-python-libs/blob/master/rich/progress_bar3.py
30 progress_bar4.py několik progress barů https://github.com/tisnik/most-popular-python-libs/blob/master/rich/progress_bar4.py
       
31 columns_panels1.py pět panelů umístěných do sloupců https://github.com/tisnik/most-popular-python-libs/blob/master/rich/colum­ns_panels1.py
32 columns_panels2.py několik panelů s naformátovaným textem https://github.com/tisnik/most-popular-python-libs/blob/master/rich/colum­ns_panels2.py
33 columns_panels3.py větší množství panelů umístěných do sloupců https://github.com/tisnik/most-popular-python-libs/blob/master/rich/colum­ns_panels3.py
       
34 table1.py jednoduchá tabulka se dvěma sloupci https://github.com/tisnik/most-popular-python-libs/blob/master/rich/table1.py
35 table2.py tabulka se třemi sloupci, text se specifikací barvy https://github.com/tisnik/most-popular-python-libs/blob/master/rich/table2.py
36 table3.py použití značky [bold] v buňkách tabulky https://github.com/tisnik/most-popular-python-libs/blob/master/rich/table3.py
       
37 text_justify.py zarovnání textu https://github.com/tisnik/most-popular-python-libs/blob/master/rich/text_justify.py

20. Odkazy na Internetu

  1. Repositář s knihovnou Rich
    https://github.com/Textualize/rich
  2. Knihovna Rich na PyPi
    https://pypi.org/project/rich/
  3. How to Use the Rich Library with Python
    https://www.freecodecamp.org/news/use-the-rich-library-in-python/
  4. Introduction (Rich, Readthedocs)
    https://rich.readthedocs.i­o/en/stable/introduction.html
  5. Awesome Python
    https://awesome-python.com/
  6. Python Awesome
    https://pythonawesome.com/about/
  7. Python Rich Library
    https://vegibit.com/python-rich-library/
  8. Python’s rich library – a tutorial
    https://softbranchdeveloper­s.com/pythons-rich-library-a-tutorial/
  9. blessed na PyPi
    https://pypi.org/project/blessed/
  10. blessed na GitHubu
    https://github.com/jquast/blessed
  11. Blessed documentation!
    https://blessed.readthedoc­s.io/en/latest/
  12. termbox-go na GitHubu
    https://github.com/nsf/termbox-go
  13. termui na GitHubu
    https://github.com/gizak/termui
  14. blessed na GitHubu
    https://github.com/chjj/blessed
  15. blessed-contrib na GitHubu
    https://github.com/yaronn/blessed-contrib
  16. tui-rs na GitHubu
    https://github.com/fdehau/tui-rs
  17. Tree structure
    https://en.wikipedia.org/wi­ki/Tree_structure
  18. Directory structure
    https://en.wikipedia.org/wi­ki/Directory_structure
  19. Decision tree
    https://en.wikipedia.org/wi­ki/Decision_tree
  20. Lightweight markup language
    https://en.wikipedia.org/wi­ki/Lightweight_markup_lan­guage
  21. Text box
    https://en.wikipedia.org/wi­ki/Text_box

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.