Trình Diễn Mọi Nội Dung Trên Nền Đen Trắng Bằng Python?

Trình Diễn Mọi Nội Dung Trên Nền Đen Trắng Bằng Python?

Python được các sysadmin/devops/developer dùng nhiều trong viết các chương trình hệ thống, viết các công cụ sinh nhanh/tự động các báo cáo. Thường là họ sẽ sử dụng màn hình console/terminal như một công cụ để xem output chương trình. Sự đơn điệu của màn hình nền đen chữ trắng có thể làm cho việc xem nhanh các báo cáo cũng khiến các user phải căng mắt ra. Việc hiển thị rich content trên "màn hình đen" luôn là một thử thách không hề đơn giản với tất cả các ngôn ngữ lập trình.

Hãy cùng tôi vượt qua thử thách này bằng cách sử dụng một thư viện của Python nhé.

Nhiều tháng trước, tôi có viết 1 bài trên codelearn về việc "làm đẹp" cho màn hình console (Tô Màu Cho Chữ Trên Terminal Với Colorama Python), nhưng dường như nó vẫn chưa đủ với nhu cầu sử dụng của user. User muốn hiển thị nhiều style hơn nữa, thậm chí là cả vẽ một bảng biểu (table) trực tiếp lên console để họ thấy dữ liệu được trực quan hơn nữa. Okie! Cứ nhận yêu cầu và khi nào được cấp "tài nguyên" (thời gian, tiền công, ...) là bắt đầu nghiên cứu thôi. Với ngôn ngữ lập trình khác thì không biết, riêng với Python, không có việc gì là khó cả, các Pythonista có đến hơn 200.000 thư viện miễn phí trên pypi.org, kiểu gì chẳng có thư viện hỗ trợ.
Sau một thời gian "nghiên cứu" các thư viện trên pypi.org, tôi đã tìm ra một thư viện khá thú vị, đủ khả năng đáp ứng nhu cầu của user là rich. Hãy cùng tôi bắt đầu tìm hiểu về thư viện này nhé.

Cài đặt thư viện.

Đầu tiên là bạn nên tạo cho mình một virtual environment mới để không làm ảnh hưởng đến cụm thư viện gốc. Hướng dẫn tạo VE ở đây nhé Làm Chủ Python Virtual Environment - Môi Trường Lập Trình Ảo ?
Từ màn hình console đã thực hiện activate virtual environment, thực hiện gọi đến thư viện cài đặt thư viện:

>pip install rich
Collecting rich
Using cached https://files.pythonhosted.org/packages/f9/a0/875fd1285885fd491540380a10f22834f3648ff5a3c3a0ed3c2013888e72/rich-9.4.0-py3-none-any.whl
Collecting typing-extensions<4.0.0,>=3.7.4 (from rich)
Using cached https://files.pythonhosted.org/packages/60/7a/e881b5abb54db0e6e671ab088d079c57ce54e8a01a3ca443f561ccadb37e/typing_extensions-3.7.4.3-py3-none-any.whl
Collecting pygments<3.0.0,>=2.6.0 (from rich)
Downloading https://files.pythonhosted.org/packages/85/c5/c437c383d5917fae9782eb6588bec8aff931afe13c76b9e8c03dacee9beb/Pygments-2.7.3-py3-none-any.whl (950kB)
|████████████████████████████████| 952kB 1.1MB/s
Collecting colorama<0.5.0,>=0.4.0 (from rich)
Using cached https://files.pythonhosted.org/packages/44/98/5b86278fbbf250d239ae0ecb724f8572af1c91f4a11edf4d36a206189440/colorama-0.4.4-py2.py3-none-any.whl
Collecting commonmark<0.10.0,>=0.9.0 (from rich)
Using cached https://files.pythonhosted.org/packages/b1/92/dfd892312d822f36c55366118b95d914e5f16de11044a27cf10a7d71bbbf/commonmark-0.9.1-py2.py3-none-any.whl
Installing collected packages: typing-extensions, pygments, colorama, commonmark, rich
Successfully installed colorama-0.4.4 commonmark-0.9.1 pygments-2.7.3 rich-9.4.0 typing-extensions-3.7.4.3

Để kiểm tra việc cài đặt thư viện, chúng ta dùng lệnh:

>pip freeze
colorama==0.4.4
commonmark==0.9.1
Pygments==2.7.3
rich==9.4.0
typing-extensions==3.7.4.3


À-há, thì ra ở thư viện này có sử dụng thư viện colorama mà tôi đã giới thiệu ở một bài từ trước.

Sử dụng thư viện rich

Để bắt đầu làm quen với rich, chúng ta sẽ đến trang giới thiệu các cách thức sử dụng của thư viện rich: https://rich.readthedocs.io/en/latest/index.html.
Sau khi nhìn qua một lượt các feature mà rich có thể cung cấp cho user thì chúng ta sẽ bắt đầu đi đến những ví dụ để hiểu về cách sử dụng thư viện này nhé.

1. Hiển thị text theo các style khác nhau.

Ví dụ đầu tiên về việc sử dụng thư viện rich: Thực hiện in ra màn hình dòng chữ: "Xin chào Quangvinh1986. Chào mừng bạn đến với CodeLearn. Hãy khám phá nhé!"

Tạo một file simple_print_rich.py với các dòng code:

from rich import print

print("Xin chào [red]Quangvinh1986[/red]. Chào mừng [underline]bạn[/underline] đến với [bold]CodeLearn[/bold]. Hãy [bold on red] khám phá [/bold on red] nhé!")

Kết quả hiển thị ra:

Như ví dụ trên, chúng ta đã sử dụng các kiểu định dạng như:
- [red] Quangvinh1986 [/red]: Đổi màu chữ từ trắng sang đỏ.
- [underline]bạn[/underline]: Gạch chân đoạn nội dung bên trong
- [bold]CodeLearn[/bold]: Làm "béo" chữ (với giao diện windows việc làm béo chữ cũng khá khó nhận ra).
- [bold on red] khám phá [/bold on red]: Làm "béo" chữ trên nền back-ground màu đỏ.

Chúng ta thấy cặp thẻ mà chúng ta đang dùng có style-code khá giống với markdown, các style mà rich cung cấp cũng gần giống với các style khi chúng ta muốn soạn thảo văn bản word vậy. Danh sách các loại style mà rich hỗ trợ, các bạn có thể xem tại https://rich.readthedocs.io/en/latest/style.html

Việc sử dụng print trong câu lệnh có thể gây ra sự nhầm lẫn với built-in function print của python. Chính vì vậy khi sử dụng rich, các pythonista sẽ sử dụng thông qua một đối tượng của class Console. Cách sử dụng được mô tả qua ví dụ sau:

# simple_rich.py
from rich.console import Console

console = Console()

console.print("HỌC LẬP TRÌNH TỪ CON SỐ 0", style="#2c31cf bold")
console.print("[#1e266d]Khởi đầu dễ dàng hơn với CodeLearn[/#1e266d]")

Thực hiện chạy trên terminal, ta thu được kết quả:

Style Class

Ở thư viện rich, ngoài cách thực hiện từng style trong mỗi dòng in ra màn hình console, chúng ta cũng có thể thực hiện định nghĩa nhiều style lại thành một style-class giống như đặt class trong CSS vậy.

# rich_style.py
from rich.console import Console
from rich.style import Style
console = Console()

base_style = Style.parse("red")
console.print("Hello World!", style = base_style)
console.print("Welcome to codelearn", style = base_style + Style(underline=True) + Style(link="https://codelearn.io/"))

Khi thực hiện chạy, chúng ta thu được kết quả:

Ở ví dụ trên, chúng ta đã thực hiện định nghĩa 1 style có tên base_style với định nghĩa là chữ màu đỏ. Ngoài ra là các Style khác với định dạng format khác nhau. Chúng cũng cho phép ghép các đối tượng của class style với nhau.

Style Theme

Giống như theme của các website, rich-theme cung cấp chức năng cho phép người dùng định nghĩa một loạt các style-class với tên khác nhau, sau đó nhúng theme vào console, khi nào sử dụng thì thực hiện gọi ra các style-class tương ứng.

# rich_theme.py
from rich.console import Console
from rich.theme import Theme

my_theme = Theme({
    "issue_color" : "white underline",
    "warning_color": "cyan",
    "major_color": "yellow",
    "cirtical_color": "magenta",
    "fatal_color": "red",
    "highlight_background": "on blue",
    "highlight_number_background": "on green"
})

console = Console(theme=my_theme)

console.print("This is information", style="issue_color")
console.print("[warning_color]warning_count: [highlight_number_background] 100 [/highlight_number_background] issues[/warning_color]")
console.print("[highlight_background][fatal_color]fatal_count: [highlight_number_background] 100 [/highlight_number_background] issues[/fatal_color][highlight_background]")

Kết quả thu được:

2. Hiển thị dữ liệu dạng bảng (table) với rich

Đây là tính năng mà tôi thích nhất khi chuyển sang dùng thư viện lib. Tính năng này cho phép tôi có thể định nghĩa ra các bảng dữ liệu theo từng cột sau đó đưa từng dòng dữ liệu vào.

# rich_table.py
from rich.console import Console
from rich.table import Table

table = Table(title="Danh sách các bài viết của Quangvinh1986 tháng 12/2020")

table.add_column("Số thứ tự", justify="right", style="cyan", no_wrap=True)
table.add_column("Tên bài viết", style="magenta")
table.add_column("Thời gian xuất bản", justify="right", style="green")

table.add_row("1", "Python-pdfkit Chuyển Đổi Mọi Nội Dung Sang PDF", "2020-12-06 09:46:19 GMT+0700")
table.add_row("2", "Làm Quen Với UnitTest Trong Python", "2020-12-10 09:48:38 GMT+0700")
table.add_row("3", "rich-content-on-terminal(draft)", "unknown")

console = Console()
console.print(table)

Kết quả thu được khá ấn tượng, rất dễ để người khác có thể nhìn vào và nắm bắt được thông tin nhanh:

Trên tài liệu của thư viện, các ví dụ về table cũng được đưa ra rất rõ ràng và dễ làm theo: https://rich.readthedocs.io/en/latest/tables.html

3. Hiển thị dữ liệu theo thời gian thực

Một tính năng "hay ho" nữa của rich là cho phép hiển thị ngay lập tức và liên tục "tự động" hiển thị dữ liệu thông qua: live

# rich_live.py
import time
import random
from datetime import datetime

from rich.live import Live
from rich.table import Table

table = Table()
table.add_column("Row ID")
table.add_column("Description")
table.add_column("Level")

levels = ["[red]FATAL", "[magenta]CRITICAL", "[yellow]MAJOR", "[cyan]warning"]

with Live(table, refresh_per_second=4):  # update 4 times a second to feel fluid
    for row in range(12):
        time.sleep(0.4)  # arbitrary delay
        # update the renderable internally
        table.add_row(str(row), "issue at {}".format(datetime.now()), random.choice(levels))

Khi các bạn chạy, kết quả sẽ hiển thị dần dần giúp người dùng có cảm giác như đang xem ai đó chạy báo cáo tự động vậy.

Cách sử dụng live, các bạn có thể tham khảo tại đường dẫn: https://rich.readthedocs.io/en/latest/live.html

Kết.

Trên đây là các ví dụ nhỏ về cách áp dụng thư viện rich để hiển thị những dữ liệu của chúng ta theo nhiều style và form mẫu khác nhau. Còn rất nhiều các tính năng khác của rich chờ các bạn khám phá tại trang tài liệu chính của thư viện. Các bạn có thể tìm kiếm những gì mình cần trên đó.
Source code chương trình được lưu trên github tại link: https://github.com/quangvinh1986/python-rich-console.
Cảm ơn các bạn đã theo dõi bài viết.
Tài liệu tham khảo: https://rich.readthedocs.io/en/latest/index.html