本文共 13772 字,大约阅读时间需要 45 分钟。
参考链接:(我承认链接这个写得更详细)。
我们都知道 MySQL 的输出一般像下边这样的(格式化输出打印,很好看):
mysql> select * from tb_person;+----+----------+-------------+------+------+-------------+---------------------+| id | name | phone | age | sex | description | create_time |+----+----------+-------------+------+------+-------------+---------------------+| 1 | zhangsan | 132****2889 | 25 | M | NoDesc | 2020-11-30 20:03:07 || 3 | lisi | 152****7873 | 18 | F | None | 2020-11-30 20:08:33 || 5 | wangwu | 136****2908 | 25 | M | Nothing | 2020-11-30 20:10:11 || 10 | zhaoliu | 138****5322 | 15 | M | Nothing | 2020-11-30 20:12:11 |+----+----------+-------------+------+------+-------------+---------------------+
就连 Ruby 都有 terminal-table 来输出这种表格,比如说 ,那么 Python 怎么像这样格式化打印结果呢?
pip3 install prettytable
[root@master ~]# pip3 install prettytableWARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.Collecting prettytable Downloading https://pypi.tuna.tsinghua.edu.cn/packages/94/d5/52e48f3bcf66f838d411ad85c3ac9550c2451d082623e2d4d4df7411ed5c/prettytable-2.0.0-py3-none-any.whlRequirement already satisfied: setuptools in /usr/lib/python3.6/site-packages (from prettytable)Collecting wcwidth (from prettytable) Downloading https://pypi.tuna.tsinghua.edu.cn/packages/59/7c/e39aca596badaf1b78e8f547c807b04dae603a433d3e7a7e04d67f2ef3e5/wcwidth-0.2.5-py2.py3-none-any.whlInstalling collected packages: wcwidth, prettytableSuccessfully installed prettytable-2.0.0 wcwidth-0.2.5
import prettytable as pt
import prettytable as pt# 按行添加数据tb = pt.PrettyTable()tb.field_names = ["id", "name", "phone", "age", "sex", "description"]tb.add_row([1, "zhangsan", "132****2889", 25, "M", "NoDesc"])tb.add_row([3, "lisi", "152****7873", 18, "F", "None"])tb.add_row([5, "wangwu", "136****2908", 25, "M", "Nothing"])tb.add_row([10,"zhaoliu", "138****5322", 15, "M", "Nothing"])print(tb)# 按列添加数据create_time = ["2020-11-30 20:03:07", "2020-11-30 20:08:33", "2020-11-30 20:10:11", "2020-11-30 20:12:11"]tb.add_column("create_time", create_time)print(tb)
[root@master python3_learning]# python3 test.py+----+----------+-------------+-----+-----+-------------+| id | name | phone | age | sex | description |+----+----------+-------------+-----+-----+-------------+| 1 | zhangsan | 132****2889 | 25 | M | NoDesc || 3 | lisi | 152****7873 | 18 | F | None || 5 | wangwu | 136****2908 | 25 | M | Nothing || 10 | zhaoliu | 138****5322 | 15 | M | Nothing |+----+----------+-------------+-----+-----+-------------++----+----------+-------------+-----+-----+-------------+---------------------+| id | name | phone | age | sex | description | create_time |+----+----------+-------------+-----+-----+-------------+---------------------+| 1 | zhangsan | 132****2889 | 25 | M | NoDesc | 2020-11-30 20:03:07 || 3 | lisi | 152****7873 | 18 | F | None | 2020-11-30 20:08:33 || 5 | wangwu | 136****2908 | 25 | M | Nothing | 2020-11-30 20:10:11 || 10 | zhaoliu | 138****5322 | 15 | M | Nothing | 2020-11-30 20:12:11 |+----+----------+-------------+-----+-----+-------------+---------------------+
看看,是不是和 MySQL 数据库查询的结果是一样的,惊喜吗?敢动吗?
它还可以输出 html 的格式:
print(tb.get_html_string())
id | name | phone | age | sex | description | create_time |
---|---|---|---|---|---|---|
1 | zhangsan | 132****2889 | 25 | M | NoDesc | 2020-11-30 20:03:07 |
3 | lisi | 152****7873 | 18 | F | None | 2020-11-30 20:08:33 |
5 | wangwu | 136****2908 | 25 | M | Nothing | 2020-11-30 20:10:11 |
10 | zhaoliu | 138****5322 | 15 | M | Nothing | 2020-11-30 20:12:11 |
网页显示效果和命令行直接打印的差不多哟!
更多信息自己凭着好奇心去探讨哟!
tb.clear() # 清空对象数据tb.clear_rows() # 清空数据行(field_names 的设置还是在的)tb.del_row(row_index) # 删除指定索引的数据行tb.get_html_string() # 转换成 html 格式tb.field_names = [...] # 设置字段名tb.border = False # 是否添加边框(无边框效果如下) id name phone age sex description create_time 1 zhangsan 132****2889 25 M NoDesc 2020-11-30 20:03:07 3 lisi 152****7873 18 F None 2020-11-30 20:08:33 10 zhaoliu 138****5322 15 M Nothing 2020-11-30 20:12:11 tb.header = False # 是否显示字段行(不显示效果如下)+----+----------+-------------+-------+---+---------+---------------------+| 1 | zhangsan | 132****2889 | 25.23 | M | NoDesc | 2020-11-30 20:03:07 || 3 | lisi | 152****7873 | 18 | F | None | 2020-11-30 20:08:33 || 5 | wangwu | 136****2908 | 25 | M | Nothing | 2020-11-30 20:10:11 || 10 | zhaoliu | 138****5322 | 15 | M | Nothing | 2020-11-30 20:12:11 |+----+----------+-------------+-------+---+---------+---------------------+tb.print_empty = True # 空数据的时候打印表框架还是空字符串(是的效果如下)++||++++tb.align['name'] = 'r' # name 字段列右对齐...
# test.json{ "title": "Hackbench Performance Testing", "unit": "KB/s", "x_name": "bs|test_size", "tables": { "fio.read_iops": { "average": { "dimensions": [ "compare_dimension", "openeuler 20.03" ], "source": [ [ "4k|1G", "4k|80G", "16k|1G", "32k|1G", "64k|1G", "128k|1G", "256k|1G", "512k|1G", "1024k|1G" ], [ "openeuler 20.03", 144076.2903315, 11601.099817, 37865.30472368628, 21145.10375497826, 14010.34254665909, 6701.240849466667, 3205.077255, 1367.476930860465, 673.3270888666667 ] ] }, "standard_deviation": { "dimensions": [ "compare_dimension", "openeuler 20.03" ], "source": [ [ "4k|1G", "4k|80G", "16k|1G", "32k|1G", "64k|1G", "128k|1G", "256k|1G", "512k|1G", "1024k|1G" ], [ "openeuler 20.03", 195, 0, 214, 205, 188, 183, 180, 191, 191 ] ] } }, "fio.write_iops": { "average": { "dimensions": [ "compare_dimension", "centos 7.6", "openeuler 20.03" ], "source": [ [ "4k|1G", "16k|1G", "32k|1G", "64k|1G", "128k|1G", "256k|1G", "512k|1G", "1024k|1G" ], [ "centos 7.6", 345243.028251, 142698.794456, 62108.34762725, 34747.729395, 26330.187008999997, 10317.85034025, 7471.708886999999, 3558.2993653999997 ], [ "openeuler 20.03", 122003.54468561111, 33528.52637123529, 31469.058358695653, 13870.135498022726, 8249.707439577778, 4329.454872088889, 1976.5380473953487, 1141.003158088889 ] ] }, "standard_deviation": { "dimensions": [ "compare_dimension", "centos 7.6", "openeuler 20.03" ], "source": [ [ "4k|1G", "16k|1G", "32k|1G", "64k|1G", "128k|1G", "256k|1G", "512k|1G", "1024k|1G" ], [ "centos 7.6", 97, 95, 122, 125, 100, 130, 101, 103 ], [ "openeuler 20.03", 174, 188, 171, 197, 181, 175, 170, 176 ] ] }, "change": { "dimensions": [ "compare_dimension", "centos 7.6 vs openeuler 20.03" ], "source": [ [ "4k|1G", "16k|1G", "32k|1G", "64k|1G", "128k|1G", "256k|1G", "512k|1G", "1024k|1G" ], [ "centos 7.6 vs openeuler 20.03", 183.0, 325.6, 97.4, 150.5, 219.2, 138.3, 278.0, 211.9 ] ] } } }}
# test.py#!/usr/bin/env python3import osimport sysimport jsonimport prettytable as pt# receive compare_template.yaml and auto pretty show compare resultsclass TableShow: def __init__(self, result_dict, row_size=8): self.title = result_dict['title'] self.tables = result_dict['tables'] self.row_size = row_size self.tb = None def show_table(self): for (table_title, table) in self.tables.items(): self.tb = pt.PrettyTable() self.tb.header = True self.set_field_names(table, table_title) self.set_align(table_title) self.add_row(table) self.print_table() def set_field_names(self, table, table_title): field_names = [table_title] field_names.extend(table['average']['source'][0]) self.tb.field_names = field_names def set_align(self, table_title): for field_name in self.tb.field_names: self.tb.align[field_name] = 'r' self.tb.align[table_title] = 'l' def add_row(self, table): row_names = ['average', 'standard_deviation', 'change'] max_size = max([len(row_name) for row_name in row_names]) for row_name in row_names: if row_name not in table: continue dimensions_size = len(table[row_name]['dimensions']) for index in range(1, dimensions_size): row = table[row_name]['source'][index] row_title = ' '. join([row_name + ' ' * (max_size - len(row_name)), row[0]]) if row_name == 'change': format_data_row = ["%.1f%%" % data for data in row[1:]] else: format_data_row = ["%.2f" % data for data in row[1:]] self.tb.add_row([row_title, *format_data_row]) def get_row_num(self): row_num, rem = divmod(len(self.tb.field_names[1:]), self.row_size) if rem > 0: row_num += 1 self.tb.row_num = row_num def print_table(self): print(self.title) self.get_row_num() for row in range(self.tb.row_num): start = 1 + row * self.row_size end = start + self.row_size # set the field names to include in displays self.tb.fields = [self.tb.field_names[0], *self.tb.field_names[start:end]] print(self.tb) print()if __name__ == '__main__': # template_yaml = sys.argv[1] # result_dict = json.loads(os.popen(f"compare -t {template_yaml}").read()) result_dict = json.load(open("test.json")) table_show = TableShow(result_dict, 9) table_show.show_table()
Hackbench Performance Testing+------------------------------------+-----------+----------+----------+----------+----------+---------+---------+---------+----------+| fio.read_iops | 4k|1G | 4k|80G | 16k|1G | 32k|1G | 64k|1G | 128k|1G | 256k|1G | 512k|1G | 1024k|1G |+------------------------------------+-----------+----------+----------+----------+----------+---------+---------+---------+----------+| average openeuler 20.03 | 144076.29 | 11601.10 | 37865.30 | 21145.10 | 14010.34 | 6701.24 | 3205.08 | 1367.48 | 673.33 || standard_deviation openeuler 20.03 | 195.00 | 0.00 | 214.00 | 205.00 | 188.00 | 183.00 | 180.00 | 191.00 | 191.00 |+------------------------------------+-----------+----------+----------+----------+----------+---------+---------+---------+----------+Hackbench Performance Testing+--------------------------------------------------+-----------+-----------+----------+----------+----------+----------+---------+----------+| fio.write_iops | 4k|1G | 16k|1G | 32k|1G | 64k|1G | 128k|1G | 256k|1G | 512k|1G | 1024k|1G |+--------------------------------------------------+-----------+-----------+----------+----------+----------+----------+---------+----------+| average centos 7.6 | 345243.03 | 142698.79 | 62108.35 | 34747.73 | 26330.19 | 10317.85 | 7471.71 | 3558.30 || average openeuler 20.03 | 122003.54 | 33528.53 | 31469.06 | 13870.14 | 8249.71 | 4329.45 | 1976.54 | 1141.00 || standard_deviation centos 7.6 | 97.00 | 95.00 | 122.00 | 125.00 | 100.00 | 130.00 | 101.00 | 103.00 || standard_deviation openeuler 20.03 | 174.00 | 188.00 | 171.00 | 197.00 | 181.00 | 175.00 | 170.00 | 176.00 || change centos 7.6 vs openeuler 20.03 | 183.0% | 325.6% | 97.4% | 150.5% | 219.2% | 138.3% | 278.0% | 211.9% |+--------------------------------------------------+-----------+-----------+----------+----------+----------+----------+---------+----------+
转载地址:http://dnjqi.baihongyu.com/