引言
在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)))
输出效果: