Display Rich Text In The Console Using Python | by Christopher Tao | Towards Data Science

Are you using the terminal more than GUI-based operating systems? Or, do you usually develop command-line interface programs using Python? Recently, I found an amazing Python library called “Rich” on GitHub, which already has 15.2k stars by the time I’m writing this article.
It can not only display text in colour and styles in the terminal but also emoji, tables, progress bars, markdown and even syntax highlighted code. If you have read one of my previous articles below:
towardsdatascience.com
The “Rich” library can almost do everything that I have introduced in that article, as well as some other awesome stuff.
In this article, I’ll introduce this library with examples to show its capabilities.
The image above shows the major features that the library can do. You can find the project on GitHub:
github.com
The library requires Python 3.6.1 or above to be functional. Installing the library is quite simple because we can use pip.
pip install rich
Let’s first look at how it can print.
It supports formatting tags and emoji.
from rich import printprint("Hello, [bold blue]Towards Data Science[/bold blue]!", ":thumbs_up:", "[u]By[/u]", "[i]Christopher Tao[/i]")
It can also automatically format a dictionary and highlight Python keywords and outputs. For example, let’s output the local environment in Python using the locals() method.
The above example shows the difference between the output with and without the rich library.
We can also install Python REPL using the rich library so that any data structures can be printed and highlighted based on the standards.
from rich import prettypretty.install(){"bool1":True, "bool2":False, "number":123.45, "string":"Hello!", "dict":{"key":"value"}, "list":[1,2,3], "class":type(1)}
You may know that we can use __doc__ and help() methods to display documentation of a Python class/object/method. However, it is hard to read in the terminal.
str.__doc__help(str)
By using the Rich library, we can use its inspect() function to pretty-print the above documentation.
from rich import inspectinspect(str, methods=True)
The flag methods will decide whether the methods are displayed in the documentation. If true, it is equivalent to help(). Otherwise, it is equivalent to __doc__.
I guess you won’t be surprised that the library can print code with syntax highlighted because we can kind of see the feature in the previous example.
Let me just illustrate it using a simple example. Below is just a random piece of code in my gist.
from rich.console import Consolefrom rich.syntax import Syntaxcode_snippet = '''def max_vote_recursive(states, days_left, index):    # Terminating conditions    if len(states) == 0 or index >= len(states) or days_left <= 0:        return 0    # If we have enough days, go to this state    votes_if_go = 0    if states[index]['days'] <= days_left:        votes_if_go = states[index]['votes'] + max_vote_recursive(states, days_left - states[index]['days'], index + 1)    # If we don't go to this state    votes_if_not_go = max_vote_recursive(states, days_left, index + 1)    return max(votes_if_go, votes_if_not_go)'''syntax = Syntax(code_snippet, "python", line_numbers=True)console = Console()console.print(syntax)
It’s like in a GUI-based IDE, super cool!
The Rich library also provides a module called “Console” that enables more customised styles of prints and some features out-of-box. We can import the module and instantiate the object as follows.
from rich.console import Consoleconsole = Console()
For example, the log() method of a console object can print a “log style” output on the screen.
console.log("We are using", console, "!")
Please note that the time is automatically added in the logs.
The console object also has a flag log_locals that can be a very useful debugging tool. It outputs all the local variables currently in the memory.
console.log("All local variables", log_locals=True)
Python has a built-in logging library which is utilised for displaying logs with different levels and formats. The Rich library can seamlessly integrate with the library to provide a further pretty-print experience.
Let’s import the logging library and initialise the log object first.
import loggingfrom rich.logging import RichHandlerFORMAT = "%(message)s"logging.basicConfig(    level="NOTSET", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()])log = logging.getLogger("rich")
Then, we can output some logs to see what happen.
log.debug("Debug Message.")log.info("Info Message.")log.warning("Warning Message.")log.error("Error Message.")log.fatal("Fatal Message.")
Very cool, our logs will be coloured in the terminal now.
I was really amazed by this feature. I’m sure you’ll, too. The Rich library can show the traceback of any expectation in a very readable way. This feature is out-of-box that is actually a combination of all of the above features.
To illustrate all the elements of the pretty traceback, we need to have relatively complex code. So, please allow me to use the screenshot from the official GitHub readme page.
The Rich library can also display a table very beautifully. More importantly, the style and word-wraps will be automatically adjusted based on the width of the terminal window.
Here is a code snippet that can generate a table using the Rich library. Eventually, it will be printed.
from rich.console import Consolefrom rich.table import Tableconsole = Console()table = Table(show_header=True, header_style="bold magenta")table.add_column("Date", style="dim", width=12)table.add_column("Title")table.add_column("Production Budget", justify="right")table.add_column("Box Office", justify="right")table.add_row(    "Dev 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118")table.add_row(    "May 25, 2018",    "[red]Solo[/red]: A Star Wars Story",    "$275,000,000",    "$393,151,347",)table.add_row(    "Dec 15, 2017",    "Star Wars Ep. VIII: The Last Jedi",    "$262,000,000",    "[bold]$1,332,539,889[/bold]",)console.print(table)
As above-mentioned, the table will fit the current width of the terminal window to make sure that the table is displayed perfectly.
The Rich library also provides amazing progress bar feature. The usage is also extremely simple.
from rich.progress import trackfrom time import sleepfor step in track(range(100), description="Writing Medium Story..."):    sleep(0.1)
Of course, the progress bar is very flexible that can be customised with a lot of aspects such as displaying multiple progress bars together and detailed progress label text as follows.
The Rich library can also display markdown text in the terminal.
I’ve created a sample markdown file beforehand. Then, we can import the Markdown module in the Rich library to display it.
from rich.console import Consolefrom rich.markdown import Markdownconsole = Console()with open("test.md") as md:    markdown = Markdown(md.read())console.print(markdown)
Although it cannot display the headers in different font sizes because of the limitation of the terminal, it still can distinguish them using different styles.
OK. Please allow me to stop here. There are just too many impressive features in this library that I can’t show them all in one article, though I have demonstrated the ones that I think are the most interested. There are still more features such as the columns, panel, padding and render groups that are also great. It is highly recommended to check them out by yourself.
medium.com
If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)