如何用Python美化打印ASCII表格?
我在寻找一种方法,可以把这样的表格美观地打印出来:
=======================
| column 1 | column 2 |
=======================
| value1 | value2 |
| value3 | value4 |
=======================
我找到了一种叫做 asciitable 的库,但它不支持边框等功能。我不需要对数据项进行复杂的格式化,它们只是字符串。我确实需要它能够自动调整列宽。
有没有其他的库或者方法,还是我需要花几分钟自己写一个?
13 个回答
40
这里有一个我写的小函数,用来显示通过SOAP API获取的SQL查询结果。这个函数需要输入一个或多个namedtuples
,这些数据会被当作表格的行来处理。如果只有一条记录,它会以不同的方式显示出来。
这个函数对我很有用,也许对你来说也是一个不错的起点:
def pprinttable(rows):
if len(rows) > 1:
headers = rows[0]._fields
lens = []
for i in range(len(rows[0])):
lens.append(len(max([x[i] for x in rows] + [headers[i]],key=lambda x:len(str(x)))))
formats = []
hformats = []
for i in range(len(rows[0])):
if isinstance(rows[0][i], int):
formats.append("%%%dd" % lens[i])
else:
formats.append("%%-%ds" % lens[i])
hformats.append("%%-%ds" % lens[i])
pattern = " | ".join(formats)
hpattern = " | ".join(hformats)
separator = "-+-".join(['-' * n for n in lens])
print hpattern % tuple(headers)
print separator
_u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t
for line in rows:
print pattern % tuple(_u(t) for t in line)
elif len(rows) == 1:
row = rows[0]
hwidth = len(max(row._fields,key=lambda x: len(x)))
for i in range(len(row)):
print "%*s = %s" % (hwidth,row._fields[i],row[i])
示例输出:
pkid | fkn | npi -------------------------------------+--------------------------------------+---- 405fd665-0a2f-4f69-7320-be01201752ec | 8c9949b9-552e-e448-64e2-74292834c73e | 0 5b517507-2a42-ad2e-98dc-8c9ac6152afa | f972bee7-f5a4-8532-c4e5-2e82897b10f6 | 0 2f960dfc-b67a-26be-d1b3-9b105535e0a8 | ec3e1058-8840-c9f2-3b25-2488f8b3a8af | 1 c71b28a3-5299-7f4d-f27a-7ad8aeadafe0 | 72d25703-4735-310b-2e06-ff76af1e45ed | 0 3b0a5021-a52b-9ba0-1439-d5aafcf348e7 | d81bb78a-d984-e957-034d-87434acb4e97 | 1 96c36bb7-c4f4-2787-ada8-4aadc17d1123 | c171fe85-33e2-6481-0791-2922267e8777 | 1 95d0f85f-71da-bb9a-2d80-fe27f7c02fe2 | 226f964c-028d-d6de-bf6c-688d2908c5ae | 1 132aa774-42e5-3d3f-498b-50b44a89d401 | 44e31f89-d089-8afc-f4b1-ada051c01474 | 1 ff91641a-5802-be02-bece-79bca993fdbc | 33d8294a-053d-6ab4-94d4-890b47fcf70d | 1 f3196e15-5b61-e92d-e717-f00ed93fe8ae | 62fa4566-5ca2-4a36-f872-4d00f7abadcf | 1
示例
>>> from collections import namedtuple
>>> Row = namedtuple('Row',['first','second','third'])
>>> data = Row(1,2,3)
>>> data
Row(first=1, second=2, third=3)
>>> pprinttable([data])
first = 1
second = 2
third = 3
>>> pprinttable([data,data])
first | second | third
------+--------+------
1 | 2 | 3
1 | 2 | 3
99
我很久以前就看到过这个问题,然后写了一个自己的表格美化工具:tabulate
.
我使用这个工具的场景是:
- 我大多数时候只想用一行代码
- 这个工具要足够聪明,能帮我找到最合适的格式
- 并且可以输出不同的纯文本格式
根据你的例子,grid
可能是最相似的输出格式:
from tabulate import tabulate
print tabulate([["value1", "value2"], ["value3", "value4"]], ["column 1", "column 2"], tablefmt="grid")
+------------+------------+
| column 1 | column 2 |
+============+============+
| value1 | value2 |
+------------+------------+
| value3 | value4 |
+------------+------------+
其他支持的格式有 plain
(没有线条),simple
(Pandoc 的简单表格),pipe
(像 PHP Markdown Extra 中的表格),orgtbl
(像 Emacs 的 org-mode 中的表格),rst
(像 reStructuredText 中的简单表格)。grid
和 orgtbl
在 Emacs 中很容易编辑。
在性能方面,tabulate
比 asciitable
稍慢,但比 PrettyTable
和 texttable
快很多。
附言:我也很喜欢把数字按照小数点对齐。所以如果有数字,默认就是这样对齐的(可以更改)。
20
不知道为什么,当我在谷歌搜索中输入'docutils'时,偶然发现了texttable这个东西,看起来正是我想要的。