楔子
記得 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 函數,有興趣可以自己研究一下。