5、Python之rich:GUI之外,终端呈现也能玩出花

引言

在Python系列文章的上一篇中,我们从print的定义出发,进一步探索了print()函数更多的用法,尤其是一些哪怕是Python老手也可能忽略的用法。没有阅读的或者需要回顾print()及输出格式化的扩展用法,可以查看上一篇文章。
虽然print()函数基本能够满足日常的需要,但是,在涉及到一些更加灵活、美观的输出时,还是有些捉襟见肘。也许你不禁要问,终端呈现也就只能这样了吗?要更美观、灵活的输出,后面只能求助于Python的GUI编程了吗?
当然,GUI编程是一个很好的、很强大的手段,后面我们也会逐步涉及到。但是,终端的呈现其实不止于此,而且,考虑到实际很多Python的应用其实会部署在服务器端,能应用的有时可能只有终端。所以,接下来,我们步会通过Python的三方模块rich,进一步挖掘终端呈现的潜力。

准备工作

如同前面文章,我们已经学习使用过的三方模块Faker一样,rich也是一个三方模块。所以,在使用之前,也需要安装。

rich模块的安装

这里,我们同样使用最简单的pip来进行安装:

pip3 install rich

说明:不同的系统环境,可能是pip或者pip3。

源码及文档

感兴趣的,可以到github查看该模块的源码,尤其examples中提供了一些rich模块的使用实例,对我们学习使用该模块,很方便。

源码地址
https://github.com/Textualize/rich
相关官方学习文档
https://rich.readthedocs.io/en/latest/index.html

用rich武装终端

需要说明的是,由于是直接对应用的终端输出的能力的封装调用,所以,以下代码,如果是在PyCharm中直接运行输出,可能是看不到完整的输出效果的。所以,以下代码的执行,我们需要换一种方式,直接在系统的终端中执行:
打开系统的终端窗口,Windows的话,可以是CMD窗口,或者PowerShell;Mac系统的话,自带的终端,或者iTerm2,强烈推荐使用iTerm2,更加灵活好用。
在终端中切换到代码文件的存放路径,然后执行命令:

python3 ./rich_test.py

说明:假设我们要执行的代码脚本文件名为rich_test.py,不同系统环境中,可能是python,或者python3。

不同的print()输出

rich模块中提供了两种不同于Python内建的print()函数:

  • rich包下的print()函数,与Python内建的print()函数同名,支持富文本的输出
  • rich.pretty包下的pprint()函数,对集合数据结构进行格式化的输出,比如list,dict,set等
rich的print()函数

通过以下代码,进行富文本的终端输出:

from rich import print

# 由于直接导入了rich中print()函数,所以内建的print()函数被覆盖,以下直接调用print()函数,都是rich的print()函数
print("[italic red underline]Hello Python")

# 如果此时,想找到内建的print()函数,可以通过import builtins
import builtins

builtins.print("[italic red underline]Hello Python")

输出结果:


第一行为带样式的rich的print()函数的输出,这里指定了斜体、红色、加下划线的样式。更多样式的使用,可以参考官方使用文档。
第二行,则是通过内建的print()函数,输出相同的内容。

集合类型数据的格式化输出

下面的代码,演示了输出字典数据,以及一个列表的数据的输出:

from rich.pretty import pprint

# locals()函数是Python内建的一个函数,用于返回一个dict,包含当前上下文环境中的所有变量
pprint(locals())

names = ['张三', '李四', '王五']
pprint(names)
# expand_all参数,默认为Fase,以下演示为True的输出效果
pprint(names, expand_all=True)

输出结果:

Console的使用

如果涉及到更多场景的输出样式,我们需要使用rich.console包下的Console来实现。比如,输出的分区,富文本的显示,动态加载效果的呈现等

from rich.console import Console
import time

console = Console()
# 终端的输出进行分区,比如这是一条分割线
console.rule('这是一条分割线')
# 通过Console的print()函数输出富文本,文本样式通过style参数指定
console.print("注意!", style="italic red on white")
# 一个加载的loading演示,会动的小猴子
with console.status('working...', spinner='monkey'):
    time.sleep(20)

输出效果:

更多的spinner的效果,可以通过命令查看:

python3 -m rich.spinner

会显示每个spinner样式的名字,及对应的动态显示效果:

动态任务进度条的呈现

上面我们通过Console.status()方法实现了一个动态loading的效果,如果我们想跟进一步动态显示一个任务处理进度的进度条的效果,可以通过rich.progress包中的对应track()函数和Progress类来分别实现单任务进度条和多任务并行的进度条效果。

from rich.progress import track, Progress
import time

# 进度条
for i in track(range(20), description='Processing...'):
    time.sleep(0.1)

# 多任务并行处理
with Progress() as progress:
    task1 = progress.add_task('[red]Downloading...', total=100)
    task2 = progress.add_task('[green]Processing...', total=100)
    task3 = progress.add_task('[cyan]Cooking...', total=100)
    while not progress.finished:
        progress.update(task1, advance=0.5)
        progress.update(task2, advance=0.3)
        progress.update(task3, advance=0.8)
        time.sleep(0.1)

输出效果:

Python对象内容查看

在Python中,如果要查看一个对象中的内容,我们可以通过内建的dir()函数来查看,但是,查看的效果不是很直观。rich中提供了inspect()函数,能够更加直观得呈现:

dir()函数

首先看下通过dir()函数查看:

from rich.progress import Progress

# 通过内建的dir()函数查看对象
print(dir(Progress()))

输出结果:

inspect()函数

通过rich的inspect()函数查看相同的对象:

from rich import inspect
from rich.progress import Progress

# 通过内建的dir()函数查看对象
print(dir(Progress()))
# 通过rich的inspect()查看对象
inspect(Progress())
# 同时查看对象中的方法
inspect(Progress(), methods=True)

输出结果:

综合案例

rich模块中,还有终端树结构、表格的呈现方式。接下来,结合之前有提过的Faker模块生成测试数据、f-string格式化的用法,以及rich中的表格的使用,我们做一个动态表格,从而更加直观地查看测试数据的生成过程。同时,借助这个案例,学习rich中表格以及动态效果呈现的使用方法:

from rich.table import Table
from rich.live import Live
import time
from faker import Faker

fk = Faker('zh_CN')
# 1、定义一个表格对象
table = Table()

# 2、定义个Live()对象,动态呈现table对象的变化过程,设置每秒钟刷新5次
with Live(table, refresh_per_second=5):  # update 5 times per second
    # 在表格中添加4列
    table.add_column('用户ID')
    time.sleep(0.4)
    table.add_column('姓名')
    time.sleep(0.4)
    table.add_column('性别')
    time.sleep(0.4)
    table.add_column('年龄')
    # 3、通过Faker生成10条测试数据,并添加到table对象中进行呈现
    for row in range(10):
        time.sleep(0.4)
        table.add_row(f"{row + 1}", fk.name(), fk.passport_gender(), str(fk.random_int(18, 50)))


输出效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫理的日知录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值