如何使用Python美化打印ASCII表格?

97

我正在寻找一种像这样漂亮打印表格的方法:

=======================
| column 1 | column 2 |
=======================
| value1   | value2   |
| value3   | value4   |
=======================

我发现了asciitable库,但它不包括边框等内容。我不需要数据项的复杂格式化,它们只是字符串。但我需要自动调整列的大小。

是否存在其他库或方法,还是我需要花费几分钟编写自己的库?


为什么不使用docutils来完成这项任务呢? - S.Lott
你如何称呼一个表?表中的数据是如何组织的?value1,value2,value3,value4……是否是列表中连续的值?我认为fomat()足以获得这样一个简单的显示,不需要在长时间的教程中学习使用库来节省时间。 - eyquem
2
@korona:不,我不是在提建议。我在问一个问题。我不知道@kdt知道什么或不知道什么。与其假设,我觉得有必要问一下。 - S.Lott
6
听起来你是假设他知道docutils,而事实上可能他不知道? - korona
2
@S.Lott 我看过docutils,虽然它当然非常适合将文本转换为html、latex等格式,但我没有看到一种方法来生成漂亮的文本表格,其中列对齐并且使用固定宽度字体看起来很漂亮。你是否误解了kdt的目标,还是我漏掉了什么? - nealmcb
可能是在Python中打印表格数据的重复问题。 - Martin Thoma
13个回答

2
这是我的解决方案:
def make_table(columns, data):
    """Create an ASCII table and return it as a string.

    Pass a list of strings to use as columns in the table and a list of
    dicts. The strings in 'columns' will be used as the keys to the dicts in
    'data.'

    Not all column values have to be present in each data dict.

    >>> print(make_table(["a", "b"], [{"a": "1", "b": "test"}]))
    | a | b    |
    |----------|
    | 1 | test |
    """
    # Calculate how wide each cell needs to be
    cell_widths = {}
    for c in columns:
        values = [str(d.get(c, "")) for d in data]
        cell_widths[c] = len(max(values + [c]))

    # Used for formatting rows of data
    row_template = "|" + " {} |" * len(columns)

    # CONSTRUCT THE TABLE

    # The top row with the column titles
    justified_column_heads = [c.ljust(cell_widths[c]) for c in columns]
    header = row_template.format(*justified_column_heads)
    # The second row contains separators
    sep = "|" + "-" * (len(header) - 2) + "|"
    # Rows of data
    rows = []
    for d in data:
        fields = [str(d.get(c, "")).ljust(cell_widths[c]) for c in columns]
        row = row_template.format(*fields)
        rows.append(row)

    return "\n".join([header, sep] + rows)

2

我使用这个小实用函数。

def get_pretty_table(iterable, header):
    max_len = [len(x) for x in header]
    for row in iterable:
        row = [row] if type(row) not in (list, tuple) else row
        for index, col in enumerate(row):
            if max_len[index] < len(str(col)):
                max_len[index] = len(str(col))
    output = '-' * (sum(max_len) + 1) + '\n'
    output += '|' + ''.join([h + ' ' * (l - len(h)) + '|' for h, l in zip(header, max_len)]) + '\n'
    output += '-' * (sum(max_len) + 1) + '\n'
    for row in iterable:
        row = [row] if type(row) not in (list, tuple) else row
        output += '|' + ''.join([str(c) + ' ' * (l - len(str(c))) + '|' for c, l in zip(row, max_len)]) + '\n'
    output += '-' * (sum(max_len) + 1) + '\n'
    return output

print get_pretty_table([[1, 2], [3, 4]], ['header 1', 'header 2'])

输出

-----------------
|header 1|header 2|
-----------------
|1       |2       |
|3       |4       |
-----------------

1
你正在在每个列之间添加一个空格output += '|' + ''.join([h + ' ' * (l - len(h)) + '|' for h, l in zip(header, max_len)]) + '\n'但是在分隔线中没有添加空格。可以通过以下方式扩展该行的 -output = '-' * (sum(max_len) + 1 + len(header)) + '\n' - ochawkeye
应该被称为 get_shitty_table() - MathCrackExchange

-1

这可以使用内置模块,通过列表和字符串推导相当紧凑地完成。接受一个格式完全相同的字典列表...

def tableit(dictlist):
    lengths = [ max(map(lambda x:len(x.get(k)), dictlist) + [len(k)]) for k in dictlist[0].keys() ]
    lenstr = " | ".join("{:<%s}" % m for m in lengths)
    lenstr += "\n"

    outmsg = lenstr.format(*dictlist[0].keys())
    outmsg += "-" * (sum(lengths) + 3*len(lengths))
    outmsg += "\n"
    outmsg += "".join(
        lenstr.format(*v) for v in [ item.values() for item in dictlist ]
    )
    return outmsg

请提交一个使用您的代码的示例。tableit([dict(a='1', b='2', c='3'), dict(a='x', b='y', c='z')]) - iuridiniz
你的代码在Python 3中不能正常工作,第2行必须更改为:lengths = [ max(list(map(lambda x:len(x.get(k)), dictlist)) + [len(k)]) for k in dictlist[0].keys() ] - iuridiniz

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