Pretty-print tabular data in Python, a library and a command-line utility.
The main use cases of the library are:
To install the Python library and the command line utility, run:
pip install tabulate
The command line utility will be installed as tabulate to bin on
Linux (e.g. /usr/bin); or as tabulate.exe to Scripts in your
Python installation on Windows (e.g. C:\Python39\Scripts\tabulate.exe).
You may consider installing the library only for the current user:
pip install tabulate --user
In this case the command line utility will be installed to
~/.local/bin/tabulate on Linux and to
%APPDATA%\Python\Scripts\tabulate.exe on Windows.
To install just the library on Unix-like operating systems:
TABULATE_INSTALL=lib-only pip install tabulate
On Windows:
set TABULATE_INSTALL=lib-only
pip install tabulate
The module provides just one function, tabulate, which takes a list of
lists or another tabular data type as the first argument, and outputs a
nicely formatted plain-text table:
>>> from tabulate import tabulate
>>> table = [["Sun",696000,1989100000],["Earth",6371,5973.6],
... ["Moon",1737,73.5],["Mars",3390,641.85]]
>>> print(tabulate(table))
----- ------ -------------
Sun 696000 1.9891e+09
Earth 6371 5973.6
Moon 1737 73.5
Mars 3390 641.85
----- ------ -------------
The following tabular data types are supported:
Tabulate is a Python3 library.
The second optional argument named headers defines a list of column
headers to be used:
>>> print(tabulate(table, headers=["Planet","R (km)", "mass (x 10^29 kg)"]))
Planet R (km) mass (x 10^29 kg)
-------- -------- -------------------
Sun 696000 1.9891e+09
Earth 6371 5973.6
Moon 1737 73.5
Mars 3390 641.85
If headers="firstrow", then the first row of data is used:
>>> print(tabulate([["Name","Age"],["Alice",24],["Bob",19]],
... headers="firstrow"))
Name Age
------ -----
Alice 24
Bob 19
If headers="keys", then the keys of a dictionary/dataframe, or column
indices are used. It also works for NumPy record arrays and lists of
dictionaries or named tuples:
>>> print(tabulate({"Name": ["Alice", "Bob"],
... "Age": [24, 19]}, headers="keys"))
Name Age
------ -----
Alice 24
Bob 19
When data is a list of dictionaries, a dictionary can be passed as headers
to replace the keys with other column labels:
>>> print(tabulate([{1: "Alice", 2: 24}, {1: "Bob", 2: 19}],
... headers={1: "Name", 2: "Age"}))
Name Age
------ -----
Alice 24
Bob 19
By default, only pandas.DataFrame tables have an additional column
called row index. To add a similar column to any other type of table,
pass showindex="always" or showindex=True argument to tabulate().
To suppress row indices for all types of data, pass showindex="never"
or showindex=False. To add a custom row index column, pass
showindex=rowIDs, where rowIDs is some iterable:
>>> print(tabulate([["F",24],["M",19]], showindex="always"))
- - --
0 F 24
1 M 19
- - --
There is more than one way to format a table in plain text. The third
optional argument named tablefmt defines how the table is formatted.
Supported table formats are:
plain tables do not use any pseudo-graphics to draw lines:
>>> table = [["spam",42],["eggs",451],["bacon",0]]
>>> headers = ["item", "qty"]
>>> print(tabulate(table, headers, tablefmt="plain"))
item qty
spam 42
eggs 451
bacon 0
simple is the default format (the default may change in future
versions). It corresponds to simple_tables in Pandoc Markdown
extensions:
>>> print(tabulate(table, headers, tablefmt="simple"))
item qty
------ -----
spam 42
eggs 451
bacon 0
github follows the conventions of GitHub flavored Markdown. It
corresponds to the pipe format without alignment colons:
>>> print(tabulate(table, headers, tablefmt="github"))
| item | qty |
|--------|-------|
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
grid is like tables formatted by Emacs'
table.el package. It corresponds to
grid_tables in Pandoc Markdown extensions:
>>> print(tabulate(table, headers, tablefmt="grid"))
+--------+-------+
| item | qty |
+========+=======+
| spam | 42 |
+--------+-------+
| eggs | 451 |
+--------+-------+
| bacon | 0 |
+--------+-------+
simple_grid draws a grid using single-line box-drawing characters:
>>> print(tabulate(table, headers, tablefmt="simple_grid"))
┌────────┬───────┐
│ item │ qty │
├────────┼───────┤
│ spam │ 42 │
├────────┼───────┤
│ eggs │ 451 │
├────────┼───────┤
│ bacon │ 0 │
└────────┴───────┘
rounded_grid draws a grid using single-line box-drawing characters with rounded corners:
>>> print(tabulate(table, headers, tablefmt="rounded_grid"))
╭────────┬───────╮
│ item │ qty │
├────────┼───────┤
│ spam │ 42 │
├────────┼───────┤
│ eggs │ 451 │
├────────┼───────┤
│ bacon │ 0 │
╰────────┴───────╯
heavy_grid draws a grid using bold (thick) single-line box-drawing characters:
>>> print(tabulate(table, headers, tablefmt="heavy_grid"))
┏━━━━━━━━┳━━━━━━━┓
┃ item ┃ qty ┃
┣━━━━━━━━╋━━━━━━━┫
┃ spam ┃ 42 ┃
┣━━━━━━━━╋━━━━━━━┫
┃ eggs ┃ 451 ┃
┣━━━━━━━━╋━━━━━━━┫
┃ bacon ┃ 0 ┃
┗━━━━━━━━┻━━━━━━━┛
mixed_grid draws a grid using a mix of light (thin) and heavy (thick) lines box-drawing characters:
>>> print(tabulate(table, headers, tablefmt="mixed_grid"))
┍━━━━━━━━┯━━━━━━━┑
│ item │ qty │
┝━━━━━━━━┿━━━━━━━┥
│ spam │ 42 │
├────────┼───────┤
│ eggs │ 451 │
├────────┼───────┤
│ bacon │ 0 │
┕━━━━━━━━┷━━━━━━━┙
double_grid draws a grid using double-line box-drawing characters:
>>> print(tabulate(table, headers, tablefmt="double_grid"))
╔════════╦═══════╗
║ item ║ qty ║
╠════════╬═══════╣
║ spam ║ 42 ║
╠════════╬═══════╣
║ eggs ║ 451 ║
╠════════╬═══════╣
║ bacon ║ 0 ║
╚════════╩═══════╝
fancy_grid draws a grid using a mix of single and
double-line box-drawing characters:
>>> print(tabulate(table, headers, tablefmt="fancy_grid"))
╒════════╤═══════╕
│ item │ qty │
╞════════╪═══════╡
│ spam │ 42 │
├────────┼───────┤
│ eggs │ 451 │
├────────┼───────┤
│ bacon │ 0 │
╘════════╧═══════╛
colon_grid is similar to grid but uses colons only to define
columnwise content alignment , without whitespace padding,
similar the alignment specification of Pandoc grid_tables:
>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
... ["strings", "numbers"], "colon_grid",
... colalign=["right", "left"]))
+-----------+-----------+
| strings | numbers |
+==========:+:==========+
| spam | 41.9999 |
+-----------+-----------+
| eggs | 451 |
+-----------+-----------+
outline is the same as the grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="outline"))
+--------+-------+
| item | qty |
+========+=======+
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
+--------+-------+
simple_outline is the same as the simple_grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="simple_outline"))
┌────────┬───────┐
│ item │ qty │
├────────┼───────┤
│ spam │ 42 │
│ eggs │ 451 │
│ bacon │ 0 │
└────────┴───────┘
rounded_outline is the same as the rounded_grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="rounded_outline"))
╭────────┬───────╮
│ item │ qty │
├────────┼───────┤
│ spam │ 42 │
│ eggs │ 451 │
│ bacon │ 0 │
╰────────┴───────╯
heavy_outline is the same as the heavy_grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="heavy_outline"))
┏━━━━━━━━┳━━━━━━━┓
┃ item ┃ qty ┃
┣━━━━━━━━╋━━━━━━━┫
┃ spam ┃ 42 ┃
┃ eggs ┃ 451 ┃
┃ bacon ┃ 0 ┃
┗━━━━━━━━┻━━━━━━━┛
mixed_outline is the same as the mixed_grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="mixed_outline"))
┍━━━━━━━━┯━━━━━━━┑
│ item │ qty │
┝━━━━━━━━┿━━━━━━━┥
│ spam │ 42 │
│ eggs │ 451 │
│ bacon │ 0 │
┕━━━━━━━━┷━━━━━━━┙
double_outline is the same as the double_grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="double_outline"))
╔════════╦═══════╗
║ item ║ qty ║
╠════════╬═══════╣
║ spam ║ 42 ║
║ eggs ║ 451 ║
║ bacon ║ 0 ║
╚════════╩═══════╝
fancy_outline is the same as the fancy_grid format but doesn't draw lines between rows:
>>> print(tabulate(table, headers, tablefmt="fancy_outline"))
╒════════╤═══════╕
│ item │ qty │
╞════════╪═══════╡
│ spam │ 42 │
│ eggs │ 451 │
│ bacon │ 0 │
╘════════╧═══════╛
presto is like tables formatted by Presto cli:
>>> print(tabulate(table, headers, tablefmt="presto"))
item | qty
--------+-------
spam | 42
eggs | 451
bacon | 0
pretty attempts to be close to the format emitted by the PrettyTables
library:
>>> print(tabulate(table, headers, tablefmt="pretty"))
+-------+-----+
| item | qty |
+-------+-----+
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
+-------+-----+
psql is like tables formatted by Postgres' psql cli:
>>> print(tabulate(table, headers, tablefmt="psql"))
+--------+-------+
| item | qty |
|--------+-------|
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
+--------+-------+
pipe follows the conventions of PHP Markdown
Extra extension.
It corresponds to pipe_tables in Pandoc. This format uses colons to
indicate column alignment:
>>> print(tabulate(table, headers, tablefmt="pipe"))
| item | qty |
|:-------|------:|
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
asciidoc formats data like a simple table of the
AsciiDoctor
format:
>>> print(tabulate(table, headers, tablefmt="asciidoc"))
[cols="<8,>7",options="header"]
|====
| item | qty
| spam | 42
| eggs | 451
| bacon | 0
|====
orgtbl follows the conventions of Emacs
org-mode, and is editable also
in the minor orgtbl-mode. Hence its name:
>>> print(tabulate(table, headers, tablefmt="orgtbl"))
| item | qty |
|--------+-------|
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
jira follows the conventions of Atlassian Jira markup language:
>>> print(tabulate(table, headers, tablefmt="jira"))
|| item || qty ||
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
rst formats data like a simple table of the
reStructuredText
format:
>>> print(tabulate(table, headers, tablefmt="rst"))
====== =====
item qty
====== =====
spam 42
eggs 451
bacon 0
====== =====
mediawiki format produces a table markup used in
Wikipedia and on other
MediaWiki-based sites:
```pycon
print(tabulate(table, headers, tablefmt="mediawiki")) {| class="wikitable" style="text-align: left;" |+ |- ! item !! style="text-align: right;"| qty |- | spam || style="text-align: right;"| 42 |- | eggs || style="text-align: right;
$ claude mcp add python-tabulate \
-- python -m otcore.mcp_server <graph>