Python的文本表格编写/打印器

12
TL;DR -> 我在PyPi上找不到任何可以将列表作为参数并将其转换为表格的模块。我之所以问这个问题是因为我在PyPI上找不到类似于实际打印字符串或将字符串写入文件的东西。
假设你有很多统计数据,需要将它们整齐地写在一个表格中,就像这样(我一直在试图教授有关不同排序算法之间差异的课程)(请注意,此处给出的示例与下面给出的代码输出不匹配。我只是为了解释我的需求而这样做,并且不会让人们必须滚动大量代码):
#########################
#   LENGTH ||| TIME(s)  #
#########################
#       0  ||| 0.00000  #
#     250  ||| 0.00600  #
#     500  ||| 0.02100  #
#     750  ||| 0.04999  #
#    1000  ||| 0.08699  #
#    1250  ||| 0.13499  #
#    1500  ||| 0.19599  #
#    1750  ||| 0.26900  #
#    2000  ||| 0.35099  #
#########################

理想情况下,我会像下面这个文件那样写一些内容以保存到文件中:一组列表,其中一个列表包含一个值集合,另一个列表包含对应的另一个值集合。

if __name__ == '__main__':
    with open(os.path.join(os.path.dirname(__file__), 'Sort Stats', 'stats_exp.txt'), 'w') as stats:
        stats.write(
            "O-######################==#######################==#######################==######################-O\n")
        stats.writelines(
            "|{0:^23}||{1:^23}||{2:^23}||{3:^23}|\n".format("Bubble Sort", "Insertion Sort", "Merge Sort (R)",
                                                            "Merge Sort (I)"))
        stats.write(
            "|#######################||#######################||#######################||#######################|\n")
        stats.write(
            "|   LENGTH  |  TIME(s)  ||   LENGTH  |  TIME(s)  ||   LENGTH  |  TIME(s)  ||   LENGTH  |  TIME(s)  |\n")
        stats.write(
            "|#######################||#######################||#######################||#######################|\n")
        for times_taken, t1, t2, t3, t4 in zip(total_lengths, sort_times_bubble, sort_times_ins, sort_times_merge_r,
                                               sort_times_merge_i):
            stats.write(
                "|{0:^11}|{1:^11}||{2:^11}|{3:^11}||{4:^11}|{5:^11}||{6:^11}|{7:^11}|\n"
                .format(
                    times_taken, str(t1)[:6],
                    times_taken, str(t2)[:6],
                    times_taken, str(t3)[:6],
                    times_taken, str(t4)[:6],
                )
            )
        stats.write(
            "O-######################==#######################==#######################==######################-O\n")

    print "Data writing complete"

正如你所看到的,它并不美观,最重要的是它不容易扩展,因为它几乎只是简单地打印出一些东西。

我想做的是创建一个模块并将其上传到PyPI。但是,如果已经有人创建了与此类似的东西,那么这将是徒劳的努力,我可以简单地fork他们的仓库,而不必从头开始编写代码。


在字典上使用pprint可能很不错? - Noctua
当方便时,只需将数据放入Pandas DataFrame中。您可以使用to_string以表格形式打印它,但它还提供其他选项,例如打印为HTML表格。我还单独编写了代码,使我能够将DataFrame的内容转储到LaTeX表格中。 - ely
2个回答

28

PrettyTable模块就是你需要的:

PrettyTable是一个简单的Python库,旨在快速轻松地在视觉上吸引人的ASCII表格中表示表格数据。

>>> import prettytable
>>> x = prettytable.PrettyTable(["Length", "Time"])
>>> x.add_row([0, 0.00000])
>>> x.add_row([250, 0.00600]) 
>>> x.add_row([500, 0.02100]) 
>>> x.add_row([750, 0.04999])    
>>> print x
+--------+---------+
| Length |   Time  |
+--------+---------+
|   0    |   0.0   |
|  250   |  0.006  |
|  500   |  0.021  |
|  750   | 0.04999 |
+--------+---------+

或者,texttable

texttable是一个模块,用于使用ASCII字符生成格式化的文本表格。

>>> import texttable
>>> x = texttable.Texttable()
>>> x.add_rows([["Length", "Time"], [0, 0.00000], [250, 0.00600], [500, 0.02100], [750, 0.04999]])
>>> print x.draw()
+--------+-------+
| Length | Time  |
+========+=======+
| 0      | 0     |
+--------+-------+
| 250    | 0.006 |
+--------+-------+
| 500    | 0.021 |
+--------+-------+
| 750    | 0.050 |
+--------+-------+

也可以参考相关主题:如何使用Python美观地打印ASCII表格?


非常感谢你的帮助,Alex!:D 我非常感激。我原本希望能够通过这个小项目创建自己的模块并贡献到PyPi,但是已经有很好的库存在了,所以我想我会修改其中一个库。:) 再次感谢你的帮助。 - Games Brainiac
@GamesBrainiac 当然,不客气。是的,现在很难发明出独特的东西了。 - alecxe
谢谢,prettytable很好用。结合ClipboardJS,可以在HTML表格旁边创建一个“复制为文本”按钮。 - Nick Woodhams
PrettyTable对我来说有问题。在https://pypi.org/project/PTable上有一个更新的分支叫做PTable,它在Python 3.7.2上运行良好。 - NZD

7

我这里提供一种解决方案,上周我写了一个测试。目前它会将所有内容右对齐,但很容易添加一些对齐参数或其他东西。

def printTable (tbl, borderHorizontal = '-', borderVertical = '|', borderCross = '+'):
    cols = [list(x) for x in zip(*tbl)]
    lengths = [max(map(len, map(str, col))) for col in cols]
    f = borderVertical + borderVertical.join(' {:>%d} ' % l for l in lengths) + borderVertical
    s = borderCross + borderCross.join(borderHorizontal * (l+2) for l in lengths) + borderCross

    print(s)
    for row in tbl:
        print(f.format(*row))
        print(s)

例子:

>>> x = [['Length', 'Time(ms)'], [0, 0], [250, 6], [500, 21], [750, 50], [1000, 87], [1250, 135], [1500, 196], [1750, 269], [2000, 351]]
>>> printTable(x)
+--------+----------+
| Length | Time(ms) |
+--------+----------+
|      0 |        0 |
+--------+----------+
|    250 |        6 |
+--------+----------+
|    500 |       21 |
+--------+----------+
|    750 |       50 |
+--------+----------+
|   1000 |       87 |
+--------+----------+
|   1250 |      135 |
+--------+----------+
|   1500 |      196 |
+--------+----------+
|   1750 |      269 |
+--------+----------+
|   2000 |      351 |
+--------+----------+

我的文件的后续版本看起来很像这样:P - Games Brainiac
我非常谦虚地感谢这个答案。我学到了一些新的Python字符串格式化技巧! :) - Games Brainiac
1
这实际上是相当巧妙的:我使用旧的字符串格式化来为新的字符串格式化格式字符串 xD。 - poke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接