• Python Rich:美化终端显示效果


    Rich库的功能就像它的名字一样,使Python编程更加丰富(rich),
    它帮助开发者在控制台(命令行)输出中创建丰富、多彩和具有格式化的文本。

    本篇总结了如何使用Rich库让我们的命令行工具更加美观。

    1. 安装

    通过pip安装:

    pip install rich
    

    使用下面的命令验证是否安装成功。

    python -m rich
    

    2. 应用示例

    Rich的功能很多,下面通过代码示例来演示其中主要的功能。

    2.1. 美化 REPL 输出

    安装python之后,在命令行输入python,就可以进入python的交互式命令行环境(REPL)。
    因为python是解释性语言,所以可以在REPL环境中交互式的运行代码:
    image.png
    注:REPL全称: Read-Eval-Print-Loop (交互式解释器)

    默认的REPL是没有颜色的,使用Rich可以美化REPL的显示,获得更好的交互效果。
    只需要导入Rich库的pretty即可。

    >>> from rich import pretty
    >>> pretty.install()
    

    再次运行上面的代码:
    image.png
    不同的数据类型会用不同的颜色来表示。

    2.2. 查看对象信息

    Rich库中还提供了一个还有用的功能,用来查看python中各个变量或对象的详细信息。
    使用前导入 inspect 函数。

    >>> from rich import inspect
    

    对于变量,查看其概括信息的方式如下:

    >>> inspect(lst_var)
    

    image.png

    查看其包含的方法:

    >>> inspect(lst_var, methods=True)
    

    image.png

    对于对象,也是一样:

    # -*- coding: utf-8 -*-
    from rich import inspect
    
    class Sample:
        def __init__(self, name, age):
            self._name = name
            self._age = age
    
        def info(self):
            print("姓名: {}, 年龄: {}".format(self.name, self.age))
    
        def set(self, name, age):
            self.name = name
            self.age = age
    
        def get(self):
            return {"name": self.name, "age": self.age}
    
        # 私有函数
        def _private(self):
            print("这是私有函数")
    
    if __name__ == "__main__":
        sa = Sample("harry", 33)
    
        # 显示对象概要信息
        inspect(sa)
    
        # 显示对象方法信息
        inspect(sa, methods=True)
    
        # 显示对象方法和私有变量,私有函数
        inspect(sa, methods=True, private=True)
    

    image.png
    Rich库的inspect函数让我们在命令行中也可以获得非常好的阅读体验。

    2.3. 动态显示内容

    动态显示在命令行中一直是个难点,而Rich库能帮助我们很容易的实现状态和进度的动态显示。

    比如,如果有多个任务在执行,可以用Rich来动态显示执行的情况。

    # -*- coding: utf-8 -*-
    
    from time import sleep
    from rich.console import Console
    
    console = Console()
    count = 5
    tasks = [f"task {n}" for n in range(1, count + 1)]
    
    
    with console.status("") as status:
        num = 1
        while tasks:
            status.update("[{}/{}] 已经完成".format(num, count))
            task = tasks.pop(0)
            sleep(1)
            num += 1
    
    print("所有任务 全部完成!")
    

    rich-status.gif
    这样就不用打印出很多行的日志信息,而是动态的显示task完成的情况。

    还有一个动态的应用是进度条,进度条虽然不能提高程序的性能,
    但是它让我们了解到程序大概运行到哪了,能够减少等待的焦虑。

    比如,传输大量文件或者下载大文件的过程中,没有进度条的话,常常会担心程序是不是卡住了。
    下面是一个模拟文件传输中使用进度条的示例:

    # -*- coding: utf-8 -*-
    
    import time
    
    from rich.progress import Progress
    
    # 模拟2个文件,一个是文件名,一个是文件大小
    files = [("windows.iso", 24000), ("debian.iso", 17000)]
    
    with Progress() as progress:
        tasks = []
        for f in files:
            task_id = progress.add_task("copy {}".format(f[0]), filename=f[0], start=False)
            progress.update(task_id, total=f[1])
    
            progress.start_task(task_id)
            # 模拟读取文件,每次读取1024字节
            total = f[1]
            buffer = 1024
            while total > 0:
                read_bytes = 0
                if total > buffer:
                    read_bytes = buffer
                    total -= buffer
                else:
                    read_bytes = total
                    total = 0
    
                progress.update(task_id, advance=read_bytes)
                time.sleep(0.2)
    
            progress.console.log("{} 传输完成!".format(f[0]))
            progress.stop_task(task_id)
    
    

    rich-progress.gif

    2.4. 复杂结构显示

    Rich库还可以帮助我们在控制台显示一些结构化的内容。

    2.4.1. 表格

    表格是最常用的一种表现形式,也是最常用的一种展示数据的方式。

    # -*- coding: utf-8 -*-
    
    from rich.console import Console
    from rich.table import Table
    
    table = Table(title="国内生产总值指数")
    
    table.add_column("年份", justify="left", style="cyan", no_wrap=True)
    table.add_column("指标", style="magenta")
    table.add_column("数值", justify="right", style="green")
    
    table.add_row("2022年", "国民总收入指数", "4432.1")
    table.add_row("2021年", "国民总收入指数", "4319.7")
    table.add_row("2020年", "国民总收入指数", "3979.1")
    table.add_row("2019年", "国民总收入指数", "3912.1")
    
    console = Console()
    console.print(table)
    

    image.png

    2.4.2. 树形

    树形结构也是常用的结构,比如展示文件夹结构:

    # -*- coding: utf-8 -*-
    
    from rich.tree import Tree
    from rich import print
    
    # 根节点
    tree = Tree("/")
    
    # usr 分支
    usr = tree.add("usr")
    fonts = usr.add("fonts")
    bin = usr.add("bin")
    lib = usr.add("lib")
    
    # home 分支
    home = tree.add("home")
    git = home.add("git")
    python = home.add("python")
    golang = home.add("golang")
    
    # projects 分支
    projects = home.add("projects")
    samples = projects.add("samples")
    work = projects.add("work")
    
    print(tree)
    
    

    image.png

    2.5. 文档和代码显示

    IT行业内,markdown文档代码几乎是绕不开的2个东西。

    然而,直接在命令行中原样显示的markdown代码的话,是很难阅读的。
    利用Rich库,可以帮助我们解析markdown的标记,高亮不同编程语言的代码,从而在命令行中获得良好的阅读体验。

    # -*- coding: utf-8 -*-
    
    from rich.console import Console
    from rich.markdown import Markdown
    
    
    md_sample = """这是一份[Markdown][1]的语法介绍。
    
    # 段落
    
    一个段落是由一个或多个连续的行构成,段落间靠一个或以上视觉上的空行划分。
    
        这是一个段落。它有两个句子。
    
        这是另一个段落。它也有
        两个句子。
    
    
    ## 代码
    
    `print("hello")`
    
    ### 列表
    
    * 无序(没有编号的)列表中的一项
        * 一个子项,要以一个制表符或者4个空格缩进
    * 无序列表中的另一个项
    1. 有序(排好序,有编号的)列表中的一项
    1. 有序列表中的另一个项
    
    
    [1]: http://daringfireball.net/projects/markdown/
    """
    
    console = Console()
    markdown = Markdown(md_sample)
    console.print(markdown)
    

    image.png
    可以看出,不同的markdown标记会解析成不同的显示效果。

    同样,对于不同的代码,也可以高亮显示:

    # -*- coding: utf-8 -*-
    
    from rich.console import Console
    from rich.syntax import Syntax
    
    py_code = """
    def hello(name):
        print("hello ", name)
    
    hello("world")
    """
    
    java_code = """
    public class HelloWorld
    {
        public static void main(String[] args)
        {
            System.out.println("Hello,World!");
        }
    }
    """
    
    c_code = """
    #include 
    int main()
    {
        printf("Hello,World!");
        return 1;
    }
    """
    
    console = Console()
    
    console.print("========================")
    console.print("[green]python 代码")
    console.print("========================")
    syntax = Syntax(py_code, "python", theme="monokai", line_numbers=True)
    console.print(syntax)
    
    console.print("========================")
    console.print("[blue]java 代码")
    console.print("========================")
    syntax = Syntax(java_code, "java", theme="monokai", line_numbers=True)
    console.print(syntax)
    
    console.print("========================")
    console.print("[red]c 代码")
    console.print("========================")
    syntax = Syntax(c_code, "c", theme="monokai", line_numbers=True)
    console.print(syntax)
    
    

    image.png
    这里只演示了3种代码,但是Rich可以支持几乎所有主流的代码。

    3. 总结

    总的来说,Python Rich库是一个强大的工具,可以让Python开发者在命令行环境中拥有更加丰富和强大的输出能力,使得数据呈现更加直观,增强了代码的可读性和调试效率。

    本篇演示了一些常用的功能,关于Rich库的其他功能和每个功能的细节可以参考其官方文档:
    https://rich.readthedocs.io/en/latest/

  • 相关阅读:
    【读书笔记】【Effective STL】在程序中使用 STL
    STM32H7使用FileX库BUG,SD卡挂载失败
    《Linux C/C++服务器开发实践》之第4章 TCP服务器编程
    利用idea新创建maven项目时的一些基本配置
    [IAGC] Kafka消费者组的负载均衡策略
    redis(主从复制、哨兵模式、集群模式)
    logback的简单配置详解
    JAVA中变量与常量
    【单片机毕业设计】【mcuclub-hj-012】基于单片机的空气质量(CO、有害混合气体)检测的设计
    ubuntu22.10 安装nginx笔记集成nginx-rtmp-module打包编译全文
  • 原文地址:https://www.cnblogs.com/wang_yb/p/18013971