跳转到主要内容

另一个纯文本表格排版器

项目描述

Project Status: Active — The project has reached a stable, usable state and is being actively developed. CI Status https://codecov.io/gh/jwodder/txtble/branch/master/graph/badge.svg https://img.shields.io/pypi/pyversions/txtble.svg MIT License

GitHub | PyPI | 问题 | 变更日志

txtble 是另一个用于创建纯文本表格的Python库。(所有好名字都已被占用,好吧?)传递一个字符串列表的列表(或其他可转换为字符串的东西),然后得到一些很棒的东西,如下所示

+---------+----------+------------------+
|Month    |Birthstone|Birth Flower      |
+---------+----------+------------------+
|January  |Garnet    |Carnation         |
|February |Amethyst  |Violet            |
|March    |Aquamarine|Jonquil           |
|April    |Diamond   |Sweetpea          |
|May      |Emerald   |Lily Of The Valley|
|June     |Pearl     |Rose              |
|July     |Ruby      |Larkspur          |
|August   |Peridot   |Gladiolus         |
|September|Sapphire  |Aster             |
|October  |Opal      |Calendula         |
|November |Topaz     |Chrysanthemum     |
|December |Turquoise |Narcissus         |
+---------+----------+------------------+

特性

  • 行可以作为列表或 dict 传递

  • 支持ANSI颜色

  • 支持Unicode全宽和组合字符

  • 控制文本的水平(左,中,右)和垂直(上,中,下)对齐

  • 沿小数点对齐数字

  • 自定义用于绘制边框的字符

  • 切换行间,列间和外部边框

  • 设置填充参差不齐行的值

  • 在左侧和右侧填充单元格

  • 设置列宽,长行自动换行以适应

  • 配置 None 值的显示方式

  • 类型注解

安装

txtble 需要 Python 3.7 或更高版本。只需使用 Python 3 的 pip 安装 txtble 及其依赖项即可(您有 pip 吗?)

python3 -m pip install txtble

示例

构建并显示一个基本表格

>>> from txtble import Txtble
>>> # Taken from /usr/share/misc/birthtoken.gz in Ubuntu Xenial's miscfiles package:
>>> HEADERS = ['Month', 'Birthstone', 'Birth Flower']
>>> DATA = [
...     ['January',   'Garnet',     'Carnation'],
...     ['February',  'Amethyst',   'Violet'],
...     ['March',     'Aquamarine', 'Jonquil'],
...     ['April',     'Diamond',    'Sweetpea'],
...     ['May',       'Emerald',    'Lily Of The Valley'],
...     ['June',      'Pearl',      'Rose'],
...     ['July',      'Ruby',       'Larkspur'],
...     ['August',    'Peridot',    'Gladiolus'],
...     ['September', 'Sapphire',   'Aster'],
...     ['October',   'Opal',       'Calendula'],
...     ['November',  'Topaz',      'Chrysanthemum'],
...     ['December',  'Turquoise',  'Narcissus'],
... ]
>>> tbl = Txtble(DATA, headers=HEADERS)
>>> print(tbl)
+---------+----------+------------------+
|Month    |Birthstone|Birth Flower      |
+---------+----------+------------------+
|January  |Garnet    |Carnation         |
|February |Amethyst  |Violet            |
|March    |Aquamarine|Jonquil           |
|April    |Diamond   |Sweetpea          |
|May      |Emerald   |Lily Of The Valley|
|June     |Pearl     |Rose              |
|July     |Ruby      |Larkspur          |
|August   |Peridot   |Gladiolus         |
|September|Sapphire  |Aster             |
|October  |Opal      |Calendula         |
|November |Topaz     |Chrysanthemum     |
|December |Turquoise |Narcissus         |
+---------+----------+------------------+

表格也可以这样构建

>>> tbl = Txtble(headers=HEADERS)
>>> tbl.extend(DATA)

或者这样

>>> tbl = Txtble(headers=HEADERS)
>>> for row in DATA:
...     tbl.append(row)

甚至这样

>>> tbl = Txtble(DATA)
>>> tbl.headers = HEADERS

表格的行可以是值的列表(如上所示)或将标题名称映射到值的 dict

>>> tbl = Txtble(
...     headers = ["Red", "Green", "Blue"],
...     data    = [
...         {"Red": "Ruby", "Green": "Emerald", "Blue": "Sapphire"},
...         {"Red": "Fire", "Green": "Earth",   "Blue": "Water"},
...     ],
... )
>>> print(tbl)
+----+-------+--------+
|Red |Green  |Blue    |
+----+-------+--------+
|Ruby|Emerald|Sapphire|
|Fire|Earth  |Water   |
+----+-------+--------+

缺失的 dict 键可以使用 dict_fill 选项填充(没有它,您会在这里得到 KeyError

>>> tbl = Txtble(
...     headers = ["Red", "Green", "Blue"],
...     data    = [
...         {"Red": "Ruby", "Green": "Emerald", "Blue": "Sapphire"},
...         {"Red": "Fire", "Green": "Earth",   "Blue": "Water"},
...         {"Red": "Hot",                      "Blue": "Cold"},
...     ],
...     dict_fill = 'UNKNOWN',
... )
>>> print(tbl)
+----+-------+--------+
|Red |Green  |Blue    |
+----+-------+--------+
|Ruby|Emerald|Sapphire|
|Fire|Earth  |Water   |
|Hot |UNKNOWN|Cold    |
+----+-------+--------+

列数自动设置为最长行的长度

>>> tbl = Txtble([
...     ['1', '1'],
...     ['Z_6', '1', 'x', 'x^2', 'x^3', 'x^4', 'x^5'],
...     ['S_3', '1', 'a', 'b', 'aba', 'ba', 'ab'],
...     ['Z_4', '1', 'x', 'x^2', 'x^3'],
...     ['V_4', '1', 'a', 'b', 'ab'],
... ])
>>> print(tbl)
+---+-+-+---+---+---+---+
|1  |1| |   |   |   |   |
|Z_6|1|x|x^2|x^3|x^4|x^5|
|S_3|1|a|b  |aba|ba |ab |
|Z_4|1|x|x^2|x^3|   |   |
|V_4|1|a|b  |ab |   |   |
+---+-+-+---+---+---+---+

…除非您已指定标题行,这限制了列数

>>> tbl.headers = ['Group', 'Elements']
>>> print(tbl)
+-----+--------+
|Group|Elements|
+-----+--------+
|1    |1       |
|Z_6  |1       |
|S_3  |1       |
|Z_4  |1       |
|V_4  |1       |
+-----+--------+

…除非您还指定了 header_fill 以用作额外列的标题

>>> tbl.header_fill = 'Extra!'
>>> print(tbl)
+-----+--------+------+------+------+------+------+
|Group|Elements|Extra!|Extra!|Extra!|Extra!|Extra!|
+-----+--------+------+------+------+------+------+
|1    |1       |      |      |      |      |      |
|Z_6  |1       |x     |x^2   |x^3   |x^4   |x^5   |
|S_3  |1       |a     |b     |aba   |ba    |ab    |
|Z_4  |1       |x     |x^2   |x^3   |      |      |
|V_4  |1       |a     |b     |ab    |      |      |
+-----+--------+------+------+------+------+------+

您可以设置列宽;长行将自动换行以适应

>>> tbl = Txtble(
...     headers=['Short Text', 'Long Text'],
...     data=[
...         [
...             'Hi there!',
...             'Lorem ipsum dolor sit amet, consectetur adipisicing elit',
...         ]
...     ],
...     widths=[20, 20],
... )
>>> print(tbl)
+--------------------+--------------------+
|Short Text          |Long Text           |
+--------------------+--------------------+
|Hi there!           |Lorem ipsum dolor   |
|                    |sit amet,           |
|                    |consectetur         |
|                    |adipisicing elit    |
+--------------------+--------------------+

您可以左对齐、右对齐或居中对齐列文本

>>> tbl = Txtble(DATA, headers=HEADERS, align=['r', 'c', 'l'])
>>> print(tbl)
+---------+----------+------------------+
|    Month|Birthstone|Birth Flower      |
+---------+----------+------------------+
|  January|  Garnet  |Carnation         |
| February| Amethyst |Violet            |
|    March|Aquamarine|Jonquil           |
|    April| Diamond  |Sweetpea          |
|      May| Emerald  |Lily Of The Valley|
|     June|  Pearl   |Rose              |
|     July|   Ruby   |Larkspur          |
|   August| Peridot  |Gladiolus         |
|September| Sapphire |Aster             |
|  October|   Opal   |Calendula         |
| November|  Topaz   |Chrysanthemum     |
| December|Turquoise |Narcissus         |
+---------+----------+------------------+

同一列中的数字可以使用 'n' 对齐方式对其小数点进行对齐

>>> tbl = Txtble(
...     headers=['Thing', 'Value'],
...     data=[
...         ['Foo', 12345],
...         ['Bar', 1234.5],
...         ['Baz', 123.45],
...         ['Quux', 12.345],
...         ['Glarch', 1.2345],
...         ['Gnusto', .12345],
...     ],
...     align=['l', 'n'],
... )
>>> print(tbl)
+------+-----------+
|Thing |Value      |
+------+-----------+
|Foo   |12345      |
|Bar   | 1234.5    |
|Baz   |  123.45   |
|Quux  |   12.345  |
|Glarch|    1.2345 |
|Gnusto|    0.12345|
+------+-----------+

Unicode 也可以使用,即使是全角字符和组合字符

>>> tbl = Txtble(
...     headers=['Wide', 'Accented'],
...     data=[
...         [
...             u'\uFF37\uFF49\uFF44\uFF45',
...             u'A\u0301c\u0301c\u0301e\u0301n\u0301t\u0301e\u0301d\u0301',
...         ]
...     ]
... )
>>> print(tbl)
+--------+--------+
|Wide    |Accented|
+--------+--------+
|Wide|Áććéńt́éd́|
+--------+--------+

您可以配置边框并使它们更复杂

>>> from txtble import ASCII_EQ_BORDERS
>>> tbl = Txtble(
...     DATA,
...     headers       = HEADERS,
...     header_border = ASCII_EQ_BORDERS,
...     row_border    = True,
... )
>>> print(tbl)
+---------+----------+------------------+
|Month    |Birthstone|Birth Flower      |
+=========+==========+==================+
|January  |Garnet    |Carnation         |
+---------+----------+------------------+
|February |Amethyst  |Violet            |
+---------+----------+------------------+
|March    |Aquamarine|Jonquil           |
+---------+----------+------------------+
|April    |Diamond   |Sweetpea          |
+---------+----------+------------------+
|May      |Emerald   |Lily Of The Valley|
+---------+----------+------------------+
|June     |Pearl     |Rose              |
+---------+----------+------------------+
|July     |Ruby      |Larkspur          |
+---------+----------+------------------+
|August   |Peridot   |Gladiolus         |
+---------+----------+------------------+
|September|Sapphire  |Aster             |
+---------+----------+------------------+
|October  |Opal      |Calendula         |
+---------+----------+------------------+
|November |Topaz     |Chrysanthemum     |
+---------+----------+------------------+
|December |Turquoise |Narcissus         |
+---------+----------+------------------+

…或者 非常 复杂

>>> from txtble import DOUBLE_BORDERS
>>> tbl = Txtble(DATA, headers=HEADERS, border_style=DOUBLE_BORDERS)
>>> print(tbl)
╔═════════╦══════════╦══════════════════╗
║Month    ║Birthstone║Birth Flower      ║
╠═════════╬══════════╬══════════════════╣
║January  ║Garnet    ║Carnation         ║
║February ║Amethyst  ║Violet            ║
║March    ║Aquamarine║Jonquil           ║
║April    ║Diamond   ║Sweetpea          ║
║May      ║Emerald   ║Lily Of The Valley║
║June     ║Pearl     ║Rose              ║
║July     ║Ruby      ║Larkspur          ║
║August   ║Peridot   ║Gladiolus         ║
║September║Sapphire  ║Aster             ║
║October  ║Opal      ║Calendula         ║
║November ║Topaz     ║Chrysanthemum     ║
║December ║Turquoise ║Narcissus         ║
╚═════════╩══════════╩══════════════════╝

有关更多信息,请参阅以下文档

API

Txtble

Txtble(data=(), **kwargs)

创建一个新的 Txtble 对象。表格的数据可以作为值行的可迭代对象传递给构造函数,其中每一行都是一个单元格值的可迭代对象或从标题名称到单元格值的映射;否则,数据开始时为空。在两种情况下,都可以通过 append()extend() 方法添加更多的数据行。

**kwargs 用于配置 Txtble 实例;请参阅下面的“配置选项”。

tbl.append(row)

在表格底部添加一行新数据。 row 可以是一个单元格值的可迭代对象或一个从标题名称到单元格值的映射。

tbl.extend(rows)

在表格底部添加零个或多个新数据行

tbl.show()str(tbl)

Txtble 实例转换为显示纯文本表格的字符串。表格单元格和非字符串的填充值将通过调用 str() 来转换;例外的是 None 值,它们将根据 none_str 选项(见下文)显示。所有制表符在构建表格之前都扩展为空格。如果任何结果字符串具有不确定的宽度(即,如果 wcwidth.wcswidth() 对其中任何一个返回负数),则抛出 IndeterminateWidthErrorValueError 的子类)。

请注意,结果字符串可能包含一个或多个嵌入的新行,但(在非常罕见的情况下)它不会以新行结束。这意味着您可以这样做 print(tbl),而不会在末尾添加空白行。

配置选项

这些选项可以作为传递给 Txtble 构造函数的关键字参数设置,也可以作为 Txtble 实例的属性设置

tbl = Txtble(data, border=False)
# Same as:
tbl = Txtble(data)
tbl.border = False
align: Union[str, Sequence[str]] = ()

一系列的对齐指定符,指示每个列的内容(按顺序)应如何水平对齐。对齐指定符是'l'(左对齐)、'c'(居中对齐)和'r'(右对齐)。align可选项设置为单个对齐指定符,将使所有列都按该方式对齐。

对齐指定符可选项包含'n',将使相关列中的所有数字都对其小数点对齐;然后'l''c''r'确定整个“数字块”如何整体对齐(这通常只有在列还包含比任何数字都长的字符串值时才有意义)。仅'n'的对齐指定符等同于'ln''nl'

align_fill: str = 'l'

如果列的数量多于align中的条目数,则额外的列将对齐设置为align_fill

border: Union[bool, BorderStyle] = True

是否在表格边缘绘制边框。可选地将border设置为BorderStyle实例,以设置用于在表格边缘绘制边框的字符。可以通过设置bottom_borderleft_borderright_bordertop_border选项来切换或美化单个边缘。

border_style: BorderStyle = ASCII_BORDERS

一个BorderStyle实例,指定用于绘制表格所有边框和横线的字符。可以通过将各自的选项(如bordercolumn_border等)设置为BorderStyle实例来覆盖边框样式。有关更多信息,请参阅下面的“BorderStyle”。

bottom_border: Union[bool, BorderStyle, None] = None

是否在表格底部边缘绘制边框。默认值None表示继承为border设置的值。bottom_border可选项设置为BorderStyle实例,以设置用于在底部边缘绘制边框的字符。

break_long_words: bool = True

是否在单词太长无法适应列宽时在单词中间强制换行。

break_on_hyphens: bool = True

是否在换行时除了空白字符外还断开连字符。

column_border: Union[bool, BorderStyle] = True

是否在单独的列之间绘制垂直线。可选地将column_border设置为BorderStyle实例,以设置用于在列之间绘制垂直线的字符。

columns: Optional[int] = None

一个可选的正整数。当设置时,每行显示给定数量的列,根据需要添加带有row_fill的单元格并丢弃多余的单元格。如果也设置了headers,则其长度必须等于columns,否则将引发ValueError。同时设置columnsheaders将使header_fill被忽略。

dict_fill: Any

如果头名称不是字典/映射行中的一个键,则将使用dict_fill的值作为对应单元格的值。如果未设置dict_fill,则缺失的键将引发KeyError

header_border: 联合[bool, BorderStyle, None] = None

是否在数据行上方(如果有头行)绘制水平线。默认值None表示只有在headersNone时才会绘制边框。header_border可以可选地设置为BorderStyle实例,以设置用于绘制数据行上方的水平线的字符。

如果headersNone并且top_border设置为真值(或从border继承真值),则不会绘制头边框。

header_fill: 任意类型 = None

headersNonecolumnsNone时,此选项确定如何处理比头多列的行。当header_fill=None时,任何额外列都将从长行中丢弃。对于所有其他值,头行将扩展到最长数据行的长度,新的头单元格将包含header_fill的值。

headers: 可选[list] = None

这是一个可选的单元格值列表,用于在表格顶部的行中显示。设置此选项还将隐式设置每行列的最小数量;有关允许额外列,请参阅header_fill

如果headers设置为空列表,则必须在尝试渲染Txtble之前将header_fill设置为非None值,否则将引发ValueError

left_border: 联合[bool, BorderStyle, None] = None

是否在表格的左侧绘制边框。默认值None表示继承为border设置的值。left_border可以可选地设置为BorderStyle实例,以设置用于绘制左侧边框的字符。

left_padding: 联合[int, str, None] = None

在每张表格细胞的左侧插入的填充。这可以是整数(插入那么多空格字符)或字符串。如果字符串,则不得包含任何换行符。默认值None表示继承为padding设置的值。

len_func: 可选[Callable[[str], int]]

用于计算字符串终端单元格宽度的函数;它应接受一个字符串参数并返回一个宽度。返回负宽度将导致Txtble引发IndeterminateWidthError。默认值(在设置为None时也使用)是with_color_stripped(wcwidth.wcswidth)(参见下方的“其他”)。

none_str: 任意类型 = ''

用于显示None值的字符串(将none_str=None设置为与设置为'None'相同)

padding: 联合[int, str] = 0

在每张表格细胞的左侧和右侧插入的填充。这可以是整数(插入那么多空格字符)或字符串。如果字符串,则不得包含任何换行符。可以通过left_paddingright_padding选项分别指定表格细胞左侧和右侧的填充。

right_border: 联合[bool, BorderStyle, None] = None

是否在表格的右边沿绘制边框。默认值 None 表示继承为 border 设置的值。right_border 可选地设置为 BorderStyle 实例,以设置用于绘制右边沿边框的字符。

right_padding: 联合 [int, str, None] = None

在每个表格单元格右侧插入的填充。这可以是整数(插入那么多空格字符)或字符串。如果为字符串,则不得包含任何换行符。默认值 None 表示继承为 padding 设置的值。

row_border: 联合 [bool, BorderStyle] = False

是否在数据行之间绘制水平线。可选地将 row_border 设置为 BorderStyle 实例,以设置用于绘制数据行之间水平线的字符。

row_fill: 任何 = ''

如果表格的行数不同,则将单元格添加到较短的行,直到所有行都对齐,添加的单元格的值为 row_fill

rstrip: bool = True

border=False 时,设置 rstrip=False 将导致每行的最后一个单元格仍然用尾随空白和 padding 填充,以达到完整的列宽。(通常,当 border=False 时,省略此空白和 padding,因为没有行尾边框对齐。)此选项在您希望将文本附加到输出的一行或多行并使其严格位于表格之外时很有用。

top_border: 联合 [bool, BorderStyle, None] = None

是否在表格的顶部边沿绘制边框。默认值 None 表示继承为 border 设置的值。top_border 可选地设置为 BorderStyle 实例,以设置用于绘制顶部边沿边框的字符。

valign: 联合 [str, Sequence[str]] = ()

一个垂直对齐指定符序列,指示每个列的内容(按顺序)应该如何垂直对齐。垂直对齐指定符是 't'(顶部对齐)、'm'(中间对齐)和 'b'(底部对齐)。valign 可选地设置为单个垂直对齐指定符,以使所有列以该方式垂直对齐。

valign_fill: str = 't'

如果 valign 中的列数多于条目数,则额外的列将它们的垂直对齐设置为 valign_fill

width_fill: Optional[int] = None

如果 widths 中的列数多于条目数,则额外的列将它们的宽度设置为 width_fill

widths: 联合 [int, Sequence[Optional[int]], None] = ()

一个整数序列,指定每个列的宽度(按顺序)。超过给定宽度的行将被包装;包装可以通过 break_long_wordsbreak_on_hyphens 选项进行配置。宽度为 None 禁用该列的包装,并将该列的宽度设置为最长行的宽度。widths 可选地设置为单个宽度,以使所有列具有该宽度。

wrap_func: Optional[Callable[[str, int], Iterable[str]]] = None

用于包裹长行的函数;它应该接受一个字符串和宽度,并返回一个字符串的可迭代对象。默认值 None 表示使用自定义函数,该函数能够正确处理全宽字符、ANSI颜色转义序列等;如果您的表格中包含此类字符串,任何用户提供的 wrap_func 都必须能够处理它们。当 wrap_func 设置为用户提供的值时,break_long_wordsbreak_on_hyphens 选项将被忽略。

边框样式

BorderStyle 类是一个列出用于绘制表格边框和规则的字符串的 namedtuple。其属性包括

属性

描述

示例

hline

水平线

vline

垂直线

ulcorner

左上角框角

urcorner

右上角框角

llcorner

左下角框角

lrcorner

右下角框角

vrtee

指向右的丁字

vltee

指向左的丁字

dhtee

指向下的丁字

uhtee

指向上的丁字

plus

十字/四向连接

txtble 提供以下预定义的 BorderStyle 实例

ASCII_BORDERS

默认边框样式。使用仅包含 ASCII 字符 -|+ 绘制边框。

+-+-+
|A|B|
+-+-+
|C|D|
+-+-+
ASCII_EQ_BORDERS

ASCII_BORDERS 类似,但使用 = 代替 -

+=+=+
|A|B|
+=+=+
|C|D|
+=+=+
LIGHT_BORDERS

使用轻量级框绘制字符。

┌─┬─┐
|A|B|
├─┼─┤
|C|D|
└─┴─┘
HEAVY_BORDERS

使用重量级框绘制字符。

┏━┳━┓
┃A┃B┃
┣━╋━┫
┃C┃D┃
┗━┻━┛
DOUBLE_BORDERS

使用双框绘制字符。

╔═╦═╗
║A║B║
╠═╬═╣
║C║D║
╚═╩═╝
DOT_BORDERS

使用 ·

·⋯·⋯·
⋮A⋮B⋮
·⋯·⋯·
⋮C⋮D⋮
·⋯·⋯·

如果您定义自己的 BorderStyle 实例,它们必须遵守以下规则

  • hline 字符串必须恰好与一个终端列宽相同(与空格字符相同的宽度)。

  • 除了 hline 之外的所有字符串必须具有相同的宽度。

  • 任何字符串都不能包含换行符。

其他

IndeterminateWidthError

ValueError 的子类。当字符串报告为具有负/不确定宽度时引发。对于默认的 len_func,当字符串包含 DEL 或 C0 或 C1 控制字符(除制表符、换行符或 ANSI 颜色转义序列外)时发生这种情况。有关问题的字符串可用作异常的 string 属性。

NumericWidthOverflowError

ValueError 的子类。当列具有非 None 宽度,列的 align 值包含 'n',并且沿小数点对列中的数字进行对齐会导致一个或多个单元格超过列的宽度时引发。

UnterminatedColorError

ValueError 的子类。当 with_color_stripped 遇到 ANSI 颜色转义序列最终未由 reset/sgr0 序列终止时引发。有关问题的字符串可用作异常的 string 属性。

with_color_stripped

一个用于应用在 len 或其类似函数上的函数装饰器,用于在传递之前从单个字符串参数中删除 ANSI 颜色序列。如果任何颜色序列后面没有跟随重置序列,则引发 UnterminatedColorError

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码分发

txtble-0.12.1.tar.gz (49.3 kB 查看哈希值)

上传 源代码

构建分发

txtble-0.12.1-py3-none-any.whl (18.6 kB 查看哈希值)

上传 Python 3

支持者