Getting Started
Tables
Painless creation of nice-looking tables of data for Python.
Starting simple
>>> from ansitable import ANSITable
>>>
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", 5.5, 6)
>>> table.row("ccccccc", 8.8, 9)
>>> table.print()
col1 column 2 has a big header column 3
aaaaaaaaa 2.2 3
bbbbbbbbbbbbb 5.5 6
ccccccc 8.8 9
This produces a table with column widths automatically chosen, headings and column data all right-justified (default).
By default output is printed to the console (stdout), but you can:
Provide a
fileoption to.print()to write to a specified output streamObtain a multi-line string version with
str(table)
Borders
You can add borders made up of regular ASCII characters:
>>> from ansitable import ANSITable, Column
>>> table = ANSITable(
... Column("col1"),
... Column("column 2 has a big header"),
... Column("column 3"),
... border="ascii"
... )
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", 5.5, 6)
>>> table.row("ccccccc", 8.8, 9)
>>> table.print()
+---------------+---------------------------+----------+
| col1 | column 2 has a big header | column 3 |
+---------------+---------------------------+----------+
| aaaaaaaaa | 2.2 | 3 |
| bbbbbbbbbbbbb | 5.5 | 6 |
| ccccccc | 8.8 | 9 |
+---------------+---------------------------+----------+
Or use ANSI box-drawing characters (supported by most terminal emulators):
>>> from ansitable import ANSITable, Column
>>> table = ANSITable(
... Column("col1"),
... Column("column 2 has a big header"),
... Column("column 3"),
... border="thick"
... )
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", 5.5, 6)
>>> table.row("ccccccc", 8.8, 9)
>>> table.print()
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ col1 ┃ column 2 has a big header ┃ column 3 ┃
┣━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━┫
┃ aaaaaaaaa ┃ 2.2 ┃ 3 ┃
┃ bbbbbbbbbbbbb ┃ 5.5 ┃ 6 ┃
┃ ccccccc ┃ 8.8 ┃ 9 ┃
┗━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┛
Other border options: "thin", "round" (thin with rounded corners), and "double".
Formatting and alignment
Specify Python format strings for columns:
>>> from ansitable import ANSITable, Column
>>> table = ANSITable(
... Column("col1"),
... Column("column 2 has a big header", "{:.3g}"),
... Column("column 3", "{:-10.4f}")
... )
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", 5.5, 6)
>>> table.row("ccccccc", 8.8, 9)
>>> table.print()
col1 column 2 has a big header column 3
aaaaaaaaa 2.2 3.0000
bbbbbbbbbbbbb 5.5 6.0000
ccccccc 8.8 9.0000
Control alignment with colalign (data) and headalign (heading):
- "<" — left
- ">" — right (default)
- "^" — center
>>> from ansitable import ANSITable, Column
>>> table = ANSITable(
... Column("col1", headalign="<"),
... Column("column 2 has a big header", colalign="^"),
... Column("column 3", colalign="<"),
... border="thick"
... )
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, 9)
>>> table.print()
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ col1 ┃ column 2 has a big header ┃ column 3 ┃
┣━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━┫
┃ aaaaaaaaa ┃ 2.2 ┃ 3 ┃
┃ bbbbbbbbbbbbb ┃ -5.5 ┃ 6 ┃
┃ ccccccc ┃ 8.8 ┃ 9 ┃
┗━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┛
Add dividing lines with .rule():
>>> from ansitable import ANSITable, Column
>>> table = ANSITable(
... Column("col1", headalign="<"),
... Column("column 2 has a big header", colalign="^"),
... Column("column 3", colalign="<"),
... border="thick"
... )
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.rule()
>>> table.row("ccccccc", 8.8, -9)
>>> table.print()
┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ col1 ┃ column 2 has a big header ┃ column 3 ┃
┣━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━┫
┃ aaaaaaaaa ┃ 2.2 ┃ 3 ┃
┃ bbbbbbbbbbbbb ┃ -5.5 ┃ 6 ┃
┣━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━┫
┃ ccccccc ┃ 8.8 ┃ -9 ┃
┗━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┛
Width constraints
Limit column width with the width argument:
>>> from ansitable import ANSITable, Column
>>> table = ANSITable(
... Column("col1", width=10),
... Column("column 2 has a big header", "{:.3g}"),
... Column("column 3", "{:-10.4f}")
... )
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", 5.5, 6)
>>> table.row("ccccccc", 8.8, 9)
>>> table.print()
col1 column 2 has a big header column 3
aaaaaaaaa 2.2 3.0000
bbbbbbbbb… 5.5 6.0000
ccccccc 8.8 9.0000
Excess text is truncated with an ellipsis (U+2026). Disable with ellipsis=False.
Color and styling
If you have the colored package installed, you can set foreground/background colors and text styles (bold, reverse, underlined, dim):
from ansitable import ANSITable, Column, Cell
table = ANSITable(
Column("col1", headalign="<", colcolor="red", headstyle="underlined"),
Column("column 2 has a big header", colalign="^", colstyle="bold"),
Column("column 3", colalign="<", colbgcolor="green"),
border="thick", bordercolor="blue"
)
table.row("aaaaaaaaa", 2.2, 3)
table.row("bbbbbbbbbbbbb", -5.5, 6)
table.row("ccccccc", 8.8, -9)
print(table)
Rendered output with colors:
| col1 | column 2 has a big header | column 3 |
|---|---|---|
| aaaaaaaaa | 2.2 | 3 |
| bbbbbbbbbbbbb | -5.5 | 6 |
| ccccccc | 8.8 | -9 |
Override styles per-row or per-cell:
from ansitable import ANSITable, Column, Cell
table = ANSITable(
Column("col1", headalign="<"),
Column("column 2 has a big header", colalign="^"),
Column("column 3", colalign="<"),
border="thick"
)
table.row("aaaaaaaaa", 2.2, 3)
table.row("bbbbbbbbbbbbb", Cell(-5.5, bgcolor="blue"), 6, bgcolor="yellow")
table.row("ccccccc", 8.8, 9)
print(table)
Rendered output with per-cell colors:
| col1 | column 2 has a big header | column 3 |
|---|---|---|
| aaaaaaaaa | 2.2 | 3 |
| bbbbbbbbbbbbb | -5.5 | 6 |
| ccccccc | 8.8 | 9 |
Sorting
Sort table rows by a column:
>>> from ansitable import ANSITable
>>> table = ANSITable("name", "score")
>>> table.row("alice", 3)
>>> table.row("bob", 1)
>>> table.row("carol", 2)
>>> table.sort("score", key=int)
ANSITable: 3 x 2: name; score
>>> table.print()
name score
bob 1
carol 2
alice 3
The .sort() method supports:
column— column name (str) or index (int)key— optional function to transform values before comparisonreverse— sort in descending order (default: False)
Horizontal rules (added with .rule()) are silently dropped from sorted output.
Export formats
Export tables to markup languages for use in documents:
Markdown:
>>> from ansitable import ANSITable
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>> print(table.markdown())
| col1 | column 2 has a big header | column 3 |
| ------------: | ------------------------: | -------: |
| aaaaaaaaa | 2.2 | 3 |
| bbbbbbbbbbbbb | -5.5 | 6 |
| ccccccc | 8.8 | -9 |
HTML:
Supports CSS styling of cells and colors.
>>> from ansitable import ANSITable
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>> print(table.html()[:200] + "...")
<table>
<tr style=''>
<th style='text-align:right;'>col1</th>
<th style='text-align:right;'>column 2 has a big header</th>
<th style='text-align:right;'>column 3</th>
</tr>
<tr style...
reStructuredText (ReST) “simple table”:
>>> from ansitable import ANSITable
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>> print(table.rest())
============= ========================= ========
col1 column 2 has a big header column 3
============= ========================= ========
aaaaaaaaa 2.2 3
bbbbbbbbbbbbb -5.5 6
ccccccc 8.8 -9
============= ========================= ========
LaTeX:
Alignment options supported.
>>> from ansitable import ANSITable
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>> print(table.latex()[:150] + "...")
\begin{tabular}{ |r|r|r| }\hline
\multicolumn{1}{|r|}{col1} & \multicolumn{1}{|r|}{column 2 has a big header} & \multicolumn{1}{|r|}{column 3}\\\hline...
Wikitable (Wikipedia):
>>> from ansitable import ANSITable
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>> print(table.wikitable())
{| class="wikitable" col1right col2right col3right
|-
! col1 !! column 2 has a big header !! column 3
|-
| aaaaaaaaa || 2.2 || 3
|-
| bbbbbbbbbbbbb || -5.5 || 6
|-
| ccccccc || 8.8 || -9
|}
CSV:
>>> from ansitable import ANSITable
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>> print(table.csv())
col1,column 2 has a big header,column 3
aaaaaaaaa,2.2,3
bbbbbbbbbbbbb,-5.5,6
ccccccc,8.8,-9
Matrices
Display NumPy arrays as formatted matrices:
>>> from ansitable import ANSIMatrix
>>> import numpy as np
>>>
>>> np.random.seed(42)
>>> formatter = ANSIMatrix(style='thick')
>>> m = np.random.rand(4, 4) - 0.5
>>> formatter.print(m)
┏ ┓
┃-0.125 0.451 0.232 0.0987 ┃
┃-0.344 -0.344 -0.442 0.366 ┃
┃ 0.101 0.208 -0.479 0.47 ┃
┃ 0.332 -0.288 -0.318 -0.317 ┃
┗ ┛
Add superscript and subscript suffixes:
>>> from ansitable import ANSIMatrix
>>> import numpy as np
>>>
>>> np.random.seed(42)
>>> formatter = ANSIMatrix(style='thick')
>>> m = np.random.rand(4, 4) - 0.5
>>> formatter.print(m, suffix_super='T', suffix_sub='3')
┏ ┓T
┃-0.125 0.451 0.232 0.0987 ┃
┃-0.344 -0.344 -0.442 0.366 ┃
┃ 0.101 0.208 -0.479 0.47 ┃
┃ 0.332 -0.288 -0.318 -0.317 ┃
┗ ┛3
Pandas integration
Convert Pandas DataFrames to ANSITable:
>>> import pandas as pd
>>> from ansitable import ANSITable
>>>
>>> df = pd.DataFrame({"calories": [420, 380, 390], "duration": [50, 40, 45]})
>>> table = ANSITable.Pandas(df, border="thin")
>>> table.print()
┌──────────┬──────────┐
│ calories │ duration │
├──────────┼──────────┤
│ 420 │ 50 │
│ 380 │ 40 │
│ 390 │ 45 │
└──────────┴──────────┘
Convert ANSITable back to DataFrame:
>>> from ansitable import ANSITable
>>> import pandas as pd
>>>
>>> table = ANSITable("col1", "column 2 has a big header", "column 3")
>>> table.row("aaaaaaaaa", 2.2, 3)
>>> table.row("bbbbbbbbbbbbb", -5.5, 6)
>>> table.row("ccccccc", 8.8, -9)
>>>
>>> df = table.pandas()
>>> print(df)
col1 column_2_has_a_big_header column_3
0 aaaaaaaaa 2.2 3
1 bbbbbbbbbbbbb -5.5 6
2 ccccccc 8.8 -9
Column names are converted to valid Python identifiers (spaces → underscores),
allowing attribute access like df.column_2_has_a_big_header.
Disable this with underscores=False.