Pretty-print tabular data in Python, a library and a command-line utility.
The main use cases of the library are:
- printing small tables without hassle: just one function call, formatting is guided by the data itself
- authoring tabular data for lightweight plain-text markup: multiple output formats suitable for further editing or transformation
- readable presentation of mixed textual and numeric data: smart column alignment, configurable number formatting, alignment by a decimal point
Installation
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 tabulateBuild status
Library usage
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:
- list of lists or another iterable of iterables
- list or another iterable of dicts (keys as columns)
- dict of iterables (keys as columns)
- list of dataclasses (field names as columns)
- two-dimensional NumPy array
- NumPy record arrays (names as columns)
- pandas.DataFrame
Tabulate is a Python3 library.
Headers
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
Row Indices
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 - - --
Table format
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"
- "simple"
- "github"
- "grid"
- "simple_grid"
- "rounded_grid"
- "heavy_grid"
- "mixed_grid"
- "double_grid"
- "fancy_grid"
- "outline"
- "simple_outline"
- "rounded_outline"
- "heavy_outline"
- "mixed_outline"
- "double_outline"
- "fancy_outline"
- "pipe"
- "orgtbl"
- "asciidoc"
- "jira"
- "presto"
- "pretty"
- "psql"
- "rst"
- "mediawiki"
- "moinmoin"
- "html"
- "unsafehtml"
- "latex"
- "latex_raw"
- "latex_booktabs"
- "latex_longtable"
- "textile"
- "tsv"
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 with the same 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:
>>> print(tabulate(table, headers, tablefmt="mediawiki")) {| class="wikitable" style="text-align: left;" |+ <!-- caption --> |- ! item !! style="text-align: right;"| qty |- | spam || style="text-align: right;"| 42 |- | eggs || style="text-align: right;"| 451 |- | bacon || style="text-align: right;"| 0 |}
moinmoin format produces a table markup used in
MoinMoin wikis: