prettytable:像数据库一样格式化输出内容
楔子
记得 MySQL 吗?如果在 MySQL 命令行查询的话,会以如下的形式进行展示。
同理,prettytable 就是用来将数据按照上述形式进行输出的,我们来看一下用法。
添加表头、添加行、添加列
类似于数据库中的表,有表头、或者说字段名,以及每一行的内容。
from prettytable import PrettyTable
# 传入的["姓名", "年龄", "出处"]相当于表头
tb = PrettyTable(["姓名", "年龄", "出处"])
# 调用add_row添加行记录
tb.add_row(["古明地觉", 16, "东方地灵殿"])
tb.add_row(["椎名真白", 18, "樱花庄的宠物女孩"])
tb.add_row(["坂上智代", 18, "Clannad"])
tb.add_row(["雨宫优子", 16, "悠久之翼"])
tb.add_row(["牧濑红莉栖", 20, "命运石之门"])
# 打印
print(tb)
"""
+------------+------+------------------+
| 姓名 | 年龄 | 出处 |
+------------+------+------------------+
| 牧濑红莉栖 | 20 | 命运石之门 |
| 古明地觉 | 16 | 东方地灵殿 |
| 椎名真白 | 18 | 樱花庄的宠物女孩 |
| 坂上智代 | 18 | Clannad |
| 雨宫优子 | 16 | 悠久之翼 |
+------------+------+------------------+
"""
当然我们还可以添加一列。
from prettytable import PrettyTable
tb = PrettyTable()
# 指定表头还可以通过tb.field_names单独指定
tb.field_names = ["姓名", "年龄", "出处"]
# 调用add_row添加行记录
tb.add_row(["古明地觉", 16, "东方地灵殿"])
tb.add_row(["椎名真白", 18, "樱花庄的宠物女孩"])
tb.add_row(["坂上智代", 18, "Clannad"])
tb.add_row(["雨宫优子", 16, "悠久之翼"])
tb.add_row(["牧濑红莉栖", 20, "命运石之门"])
# 调用add_column添加一列:列名、数据
tb.add_column("性别", ["女"] * 5)
# 打印
print(tb)
"""
+------------+------+------------------+------+
| 姓名 | 年龄 | 出处 | 性别 |
+------------+------+------------------+------+
| 古明地觉 | 16 | 东方地灵殿 | 女 |
| 椎名真白 | 18 | 樱花庄的宠物女孩 | 女 |
| 坂上智代 | 18 | Clannad | 女 |
| 雨宫优子 | 16 | 悠久之翼 | 女 |
| 牧濑红莉栖 | 20 | 命运石之门 | 女 |
+------------+------+------------------+------+
"""
从数据源中导入数据
prettytable 支持从 csv、数据库、html 等数据源中导入数据。但是说实话,从数据源读取数据我们一般使用 pandas,并且还会伴随着数据处理。而使用 prettytable 一般是为了使得程序中输出的某些信息(比如日志信息)更好的展示,如果只是展示读取的文件内容,还不如用Excel、Navicat等工具查看呢。
import pymysql
from prettytable import from_csv
from prettytable import from_db_cursor
# 从csv中读取数据
with open("xxx.csv") as f:
tb = from_csv(f)
print(tb)
# 从数据库中读取数据
conn = pymysql.connect()
cursor = conn.cursor()
cursor.execute("select * from t")
tb = from_db_cursor(cursor)
print(tb)
可以创建数据集进行查看。
输出指定行、指定列
我们也可以输出 table 的指定行、指定列。
from prettytable import PrettyTable
tb = PrettyTable()
tb.field_names = ["姓名", "年龄", "出处"]
tb.add_row(["古明地觉", 16, "东方地灵殿"])
tb.add_row(["椎名真白", 18, "樱花庄的宠物女孩"])
tb.add_row(["坂上智代", 18, "Clannad"])
tb.add_row(["雨宫优子", 16, "悠久之翼"])
tb.add_row(["牧濑红莉栖", 20, "命运石之门"])
# fields用于选择输出的列,start和end用于选择输出的开始行和结束行
print(tb.get_string(fields=["姓名", "年龄"], start=1, end=3))
"""
+----------+------+
| 姓名 | 年龄 |
+----------+------+
| 椎名真白 | 18 |
| 坂上智代 | 18 |
+----------+------+
"""
# 此外可以用来进行排序
print(tb.get_string(sortby="年龄", reversesort=True))
"""
+------------+------+------------------+
| 姓名 | 年龄 | 出处 |
+------------+------+------------------+
| 牧濑红莉栖 | 20 | 命运石之门 |
| 椎名真白 | 18 | 樱花庄的宠物女孩 |
| 坂上智代 | 18 | Clannad |
| 雨宫优子 | 16 | 悠久之翼 |
| 古明地觉 | 16 | 东方地灵殿 |
+------------+------+------------------+
"""
说实话,也不常用。与其选择性输出,还不如一开始就不要。
设置表格样式
可以通过 set_style 设置样式。
from prettytable import PrettyTable
import prettytable
tb = PrettyTable()
# 指定表头还可以通过tb.field_names单独指定
tb.field_names = ["姓名", "年龄", "出处"]
# 调用add_row添加行记录
tb.add_row(["古明地觉", 16, "东方地灵殿"])
tb.add_row(["椎名真白", 18, "樱花庄的宠物女孩"])
tb.add_row(["坂上智代", 18, "Clannad"])
tb.add_row(["雨宫优子", 16, "悠久之翼"])
tb.add_row(["牧濑红莉栖", 20, "命运石之门"])
# 表格样式有以下几种:DEFAULT、MSWORD_FRIENDLY、PLAIN_COLUMNS、RANDOM
# 我们之前的就是DEFAULT
tb.set_style(prettytable.MSWORD_FRIENDLY)
print(tb)
"""
| 姓名 | 年龄 | 出处 |
| 古明地觉 | 16 | 东方地灵殿 |
| 椎名真白 | 18 | 樱花庄的宠物女孩 |
| 坂上智代 | 18 | Clannad |
| 雨宫优子 | 16 | 悠久之翼 |
| 牧濑红莉栖 | 20 | 命运石之门 |
"""
tb.set_style(prettytable.PLAIN_COLUMNS)
print(tb)
"""
姓名 年龄 出处
古明地觉 16 东方地灵殿
椎名真白 18 樱花庄的宠物女孩
坂上智代 18 Clannad
雨宫优子 16 悠久之翼
牧濑红莉栖 20 命运石之门
"""
tb.set_style(prettytable.RANDOM)
print(tb)
"""
古明地觉 16 东方地灵殿
椎名真白 18 樱花庄的宠物女孩
坂上智代 18 Clannad
雨宫优子 16 悠久之翼
牧濑红莉栖 20 命运石之门
"""
说实话,还是默认的DEFAULT最好看。
设置对齐方式
from prettytable import PrettyTable
tb = PrettyTable()
# 指定表头还可以通过tb.field_names单独指定
tb.field_names = ["姓名", "年龄", "出处"]
# 调用add_row添加行记录
tb.add_row(["古明地觉", 16, "东方地灵殿"])
tb.add_row(["椎名真白", 18, "樱花庄的宠物女孩"])
tb.add_row(["坂上智代", 18, "Clannad"])
tb.add_row(["雨宫优子", 16, "悠久之翼"])
tb.add_row(["牧濑红莉栖", 20, "命运石之门"])
# l代表左对齐,c代表居中,r代表右对齐
tb.align["姓名"] = "l"
tb.align["年龄"] = "c"
tb.align["出处"] = "r"
print(tb)
"""
+------------+------+------------------+
| 姓名 | 年龄 | 出处 |
+------------+------+------------------+
| 古明地觉 | 16 | 东方地灵殿 |
| 椎名真白 | 18 | 樱花庄的宠物女孩 |
| 坂上智代 | 18 | Clannad |
| 雨宫优子 | 16 | 悠久之翼 |
| 牧濑红莉栖 | 20 | 命运石之门 |
+------------+------+------------------+
"""
设置边框样式
在 PrettyTable 中,边框由三个部分组成,横边框,竖边框,和边框连接符(横竖交叉的链接符号)。
from prettytable import PrettyTable
tb = PrettyTable()
# 指定表头还可以通过tb.field_names单独指定
tb.field_names = ["姓名", "年龄", "出处"]
# 调用add_row添加行记录
tb.add_row(["古明地觉", 16, "东方地灵殿"])
tb.add_row(["椎名真白", 18, "樱花庄的宠物女孩"])
tb.add_row(["坂上智代", 18, "Clannad"])
tb.add_row(["雨宫优子", 16, "悠久之翼"])
tb.add_row(["牧濑红莉栖", 20, "命运石之门"])
# 是否显示边框,默认为True
tb.border = True
# 横边框
tb.horizontal_char = '^'
# 竖边框
tb.vertical_char = '>'
# 边框连接符
tb.junction_char='~'
print(tb)
"""
~^^^^^^^^^^^^~^^^^^^~^^^^^^^^^^^^^^^^^^~
> 姓名 > 年龄 > 出处 >
~^^^^^^^^^^^^~^^^^^^~^^^^^^^^^^^^^^^^^^~
> 古明地觉 > 16 > 东方地灵殿 >
> 椎名真白 > 18 > 樱花庄的宠物女孩 >
> 坂上智代 > 18 > Clannad >
> 雨宫优子 > 16 > 悠久之翼 >
> 牧濑红莉栖 > 20 > 命运石之门 >
~^^^^^^^^^^^^~^^^^^^~^^^^^^^^^^^^^^^^^^~
"""
我们看到以上的所有示例,貌似输出的都不是很规整啊。其实这是因为我们输出的中文,如果是英文,那么会输出的很漂亮。
from prettytable import PrettyTable
tb = PrettyTable()
# 指定表头还可以通过tb.field_names单独指定
tb.field_names = ["name", "age", "where"]
# 调用add_row添加行记录
tb.add_row(["komeiji satori", 16, "touhou project"])
tb.add_row(["shiina mashiro", 18, "sakurasou"])
tb.add_row(["sakaue tomoyo", 18, "Clannad"])
tb.add_row(["amamiya yuuko", 16, "ef"])
tb.add_row(["makise kurisu", 20, "steins;gate"])
print(tb)
"""
+----------------+-----+----------------+
| name | age | where |
+----------------+-----+----------------+
| komeiji satori | 16 | touhou project |
| shiina mashiro | 18 | sakurasou |
| sakaue tomoyo | 18 | Clannad |
| amamiya yuuko | 16 | ef |
| makise kurisu | 20 | steins;gate |
+----------------+-----+----------------+
"""
小结
总的来说,在打印结构化日志信息的时候,这个库还是很有用的,当然我们也可以自己实现一个。除了这个这个 prettytable 之外,还有一个 pretty_errors,这个库是专门用来美化输出的异常信息的,举个栗子。
import pretty_errors # 只需要导入这个库即可
def f():
g()
def g():
h()
def h():
1 / 0
f()
这个库实际上是将异常信息进行删减,并做了高亮、加粗显示,当然这个库我们也可以自己实现,核心部分就是重写 sys.excepthook 函数,有兴趣可以自己研究一下。
如果觉得文章对您有所帮助,可以请囊中羞涩的作者喝杯柠檬水,万分感谢,愿每一个来到这里的人都生活愉快,幸福美满。
微信赞赏
支付宝赞赏