A clean and elegant way to print text tables in Python with minimal boilerplate code
Project description
nicetable
- A clean and elegant way to print text tables in Python with minimal boilerplate code.
- Built with modern Python (including type annotations) and has an extensive test suite. Requires Python 3.6 and up.
Typical usage
-
Import:
from nicetable.nicetable import NiceTable
-
Create a
NiceTable
, providing aList
of column names.
You can optionally pick a table layout, or override any formatting option:
out = NiceTable(['Part ID','Weight(kg)'])
out = NiceTable(['Part ID','Weight(kg)'], layout='grep')
out = NiceTable(['Part ID','Weight(kg)'], layout='csv', header=False)
-
Append new rows by calling
append()
, passing aList
of values:
out.append(my_list)
out.append(['626kst/j8',1.37])
-
Print:
print(out)
Example
The class function NiceTable.supported_layouts()
returns a List
of [name, description] of all the builtin layouts.
This example uses NiceTable
to print that list with the default table layout:
from nicetable.nicetable import NiceTable
out = NiceTable(['Layout', 'Description'])
for layout in NiceTable.builtin_layouts():
out.append(layout)
print(out)
Output:
+-----------+------------------------------------------------------------------------------------------------------+
| Layout | Description |
+-----------+------------------------------------------------------------------------------------------------------+
| csv | comma-separated values with a one-line header. |
| default | fixed-width table with data auto-alignment. |
| grep | tab-separated values with no header. Great for CLI output, easily post-processed by cut, grep etc. |
| md | for tables inside Markdown(.md) files, using the GFM table extension. Ex: README.md on github. |
| tsv | tab-separated values with a one-line header. |
+-----------+------------------------------------------------------------------------------------------------------+
Layouts and formatting settings
You can pick a table layout in the constructor, with the layout=
parameter.
In addition, you can change the layout or override any other formatting settings at any time, if needed.
Internally, NiceTable
stores the values as-is, and generates formatted strings from them only when the table is printed.
The next example uses the builtin NiceTable.SAMPLE_JSON
, which returns some sample JSON data.
The code loops over a list of dictionaries, cherry-picking some values into the table columns. It prints the table, than changes the layout to csv
and overrides a formatting option (changes the separator from ,
to |
) before printing it again.
import json
from nicetable.nicetable import NiceTable
out = NiceTable(['Name', 'Type', 'Height(cm)', 'Weight(kg)'], layout='default')
for pokemon in json.loads(NiceTable.SAMPLE_JSON):
out.append([pokemon['name'], pokemon['type'], pokemon['height'], pokemon['weight']])
print('-- default format --\n')
print(out)
out.layout = 'csv'
out.sep_vertical = '|'
print('-- CSV with a pipe separator --\n')
print(out)
Output:
-- default format --
+-------------+----------------+--------------+--------------+
| Name | Type | Height(cm) | Weight(kg) |
+-------------+----------------+--------------+--------------+
| Bulbasaur | Grass/Poison | 70 | 6.901 |
| Pikachu | Electric | 40 | 6.100 |
| Mewtwo | Psychic | 200 | 122.000 |
+-------------+----------------+--------------+--------------+
-- CSV with a pipe separator --
Name|Type|Height(cm)|Weight(kg)
Bulbasaur|Grass/Poison|70|6.901
Pikachu|Electric|40|6.1
Mewtwo|Psychic|200|122
Note that the default
layout automatically identify numeric columns and print them well-aligned to the right (see next section).
For example, the last column input was 6.901, 6.1 (float
), 122 (int
), as can be seen in the csv
output.
Cell adjustment
- Cell contents can be adjusted
left
,center
orright
, and are space-padded to the width of the longest value in the column (see also next section on wrapping).
Alternatively, cell contents can be kept as-is withcompact
adjustment, though it means that the table vertical lines will not align (this is used in some layouts such ascsv
). - The default adjustment is
auto
, meaning that numeric columns (those with only numbers or None values) are adjustedright
, and non-numeric columns are adjustedleft
. - Numeric columns automatically well-aligned, meaning all their ones digit are printed in the same position.
To print them as strings, add astrict_
prefix to the adjust, likestrict_left
. For example:
+-----------------+-------------------+------------------+---------------+-----------------+----------------+
| standard left | standard center | standard right | strict_left | strict_center | strict_right |
+-----------------+-------------------+------------------+---------------+-----------------+----------------+
| 6.901 | 6.901 | 6.901 | 6.901 | 6.901 | 6.901 |
| 6.000 | 6.000 | 6.000 | 6 | 6 | 6 |
| 1.000 | 1.000 | 1.000 | 1 | 1 | 1 |
| 122.000 | 122.000 | 122.000 | 122 | 122 | 122 |
+-----------------+-------------------+------------------+---------------+-----------------+----------------+
The example above uses long column names on purpose, otherwise left
, center
and right
would look the same,
as all the numbers in each column have the same fixed width (based on their longest column value).
Text wrapping and newlines
NiceTable
supports handling long values and newlines in both column names and cell values.
Text wrapping
When a value is longer than value_max_len
, it handled by a value_too_long_policy
policy.
The default policy is wrap
, which means the value will be broken to multiple lines every value_max_len
characters.
Alternatively, specify the truncate
policy to have to values truncated.
The following examples demonstrates the two policies:
out = NiceTable(['Code', 'Product Description(Long)'])
out.append([1, 'Boeing 777. Batteries not included. May contain nuts.'])
out.append([2, 'Sack of sand'])
print(out)
out.value_max_len = 19
print(out)
out.value_too_long_policy = 'truncate'
print(out)
Output:
+--------+---------------------------------------------------------+
| Code | Product Description(Long) |
+--------+---------------------------------------------------------+
| 1 | Boeing 777. Batteries not included. May contain nuts. |
| 2 | Sack of sand |
+--------+---------------------------------------------------------+
+--------+-----------------------+
| Code | Product Description |
| | (Long) |
+--------+-----------------------+
| 1 | Boeing 777. Batteri |
| | es not included. Ma |
| | y contain nuts. |
| 2 | Sack of sand |
+--------+-----------------------+
+--------+-----------------------+
| Code | Product Description |
+--------+-----------------------+
| 1 | Boeing 777. Batteri |
| 2 | Sack of sand |
+--------+-----------------------+
Newlines
When newlines are encountered in a column name or a value, they by default cause the text to wrap. Alternatively, you can ask that newlines will be replaced, by setting value_newline_replace
to an alternative string (default is None
).
The following example first shows the default behavior, and than shows replacing newlines with the string \n
:
out = NiceTable(['Code', 'Product Description\n(Long)']) \
.append([1, 'Boeing 777\nBatteries not included.\nMay contain nuts.']) \
.append([2, 'Sack of sand'])
print(out)
out.value_newline_replace = '\\n'
print(out)
Output:
+--------+---------------------------+
| Code | Product Description |
| | (Long) |
+--------+---------------------------+
| 1 | Boeing 777 |
| | Batteries not included. |
| | May contain nuts. |
| 2 | Sack of sand |
+--------+---------------------------+
+--------+----------------------------------------------------------+
| Code | Product Description\n(Long) |
+--------+----------------------------------------------------------+
| 1 | Boeing 777\nBatteries not included.\nMay contain nuts. |
| 2 | Sack of sand |
+--------+----------------------------------------------------------+
Escaping
TODO...
value_escape_type
value_escape_char
Table-level settings
Below is the list of the table-level settings, which you can directly set.
For example: out.header = False
Setting | Type | Default | Description |
---|---|---|---|
header | bool | 1 | whether the table header will be printed |
header_sepline | bool | 1 | if the header is printed, whether a sepline will be printed after it |
header_adjust | str | left | adjust of the column names, one of: ['left', 'center', 'right', 'compact'] |
sep_vertical | str | | | a vertical separator string |
sep_horizontal | str | - | a horizontal separator string |
sep_cross | str | + | a crossing separator string (where vertical and horizontal separators meet) |
border_top | bool | 1 | whether the table top border will be printed |
border_bottom | bool | 1 | whether the table bottom border will be printed |
border_left | bool | 1 | whether the table left border will be printed |
border_right | bool | 1 | whether the table right border will be printed |
cell_adjust | str | auto | adjust of the values, one of: ['auto', 'left', 'center', 'right', 'compact', 'strict_left', 'strict_center', 'strict_right'] |
cell_spacing | int | 2 | number of spaces to add to each side of a value |
value_min_len | int | 1 | minimal string length of a value. Shorter values will be space-padded |
value_max_len | int | 9999 | maximum string length of a value |
value_too_long_policy | str | wrap | handling of a string longer than value_max_len , one of: ['truncate', 'wrap'] |
value_newline_replace | str | None | if set, replace newlines in string value with this |
value_none_string | str | None | string representation of the None value |
value_escape_type | str | ignore | handling of sep_vertical inside a value, one of: ['remove', 'replace', 'prefix', 'ignore'] |
value_escape_char | str | \ | a string to replace or prefix sep_vertical , based on value_escape_type |
value_func | function | None | a function to pre-process the value before any other settings apply |
The table above was generated by iterating on NiceTable.FORMATTING_SETTINGS
and using the md
layout:
from nicetable.nicetable import NiceTable
out = NiceTable(['Setting', 'Type', 'Default', 'Description'], layout='md')
for setting in NiceTable.FORMATTING_SETTINGS:
out.append(setting)
print(out)
Column-level settings
The set_col_options()
function sets allows you to set the following settings at the column-level:
Parameter | Meaning |
---|---|
adjust | overrides the table-wide cell_adjust |
max_len | overrides the table-wide value_max_len |
newline_replace | overrides the table-wide value_newline_replace |
none_string | overrides the table-wide value_none_string |
func | overrides the table-wide value_func |
This function accepts either a column name or a column position for the first parameter. For example:
import json
from nicetable.nicetable import NiceTable
out = NiceTable(['Name', 'Type', 'Height(cm)', ' Weight(kg)'])
for pokemon in json.loads(NiceTable.SAMPLE_JSON):
out.append([pokemon['name'], pokemon['type'], pokemon['height'], pokemon['weight']])
# set the first column options by position
out.set_col_options(0, adjust='center')
# set the second column options by column name
out.set_col_options('Type',
func=lambda x: x.lower() if x != 'Electric' else None,
none_string = 'N/A')
print(out)
Output:
+-------------+----------------+--------------+---------------+
| Name | Type | Height(cm) | Weight(kg) |
+-------------+----------------+--------------+---------------+
| Bulbasaur | grass/poison | 70 | 6.901 |
| Pikachu | N/A | 40 | 6.100 |
| Mewtwo | psychic | 200 | 122.000 |
+-------------+----------------+--------------+---------------+
Others
get_column(col)
returns a List
of the column values.
Adding a custom layout
To add a custom layout based on the existing options, you can inherit from NiceTable
and define your own layout function.
The description of your function will be incorporated in the builtin_layouts()
output
from nicetable.nicetable import NiceTable
class MyNiceTable(NiceTable):
def _layout_as_winter_columns(self) -> None:
"""Table with a winter-themed separator. Quite Ugly."""
self.sep_vertical = '❄☂🌧☂❄'
self.sep_cross = '❄☂🌧☂❄'
self.sep_horizontal = 'ˣ'
out = MyNiceTable(['Layout', 'Description'], layout='winter_columns')
for layout in MyNiceTable.builtin_layouts():
out.append(layout)
print(out)
Output:
❄☂🌧☂❄ˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣ❄☂🌧☂❄ˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣ❄☂🌧☂❄
❄☂🌧☂❄ Layout ❄☂🌧☂❄ Description ❄☂🌧☂❄
❄☂🌧☂❄ˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣ❄☂🌧☂❄ˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣ❄☂🌧☂❄
❄☂🌧☂❄ csv ❄☂🌧☂❄ comma-separated values with a one-line header. ❄☂🌧☂❄
❄☂🌧☂❄ default ❄☂🌧☂❄ fixed-width table with data auto-alignment. ❄☂🌧☂❄
❄☂🌧☂❄ grep ❄☂🌧☂❄ tab-separated values with no header. Great for CLI output, easily post-processed by cut, grep etc. ❄☂🌧☂❄
❄☂🌧☂❄ md ❄☂🌧☂❄ for tables inside Markdown(.md) files, using the GFM table extension. Ex: README.md on github. ❄☂🌧☂❄
❄☂🌧☂❄ tsv ❄☂🌧☂❄ tab-separated values with a one-line header. ❄☂🌧☂❄
❄☂🌧☂❄ winter_columns ❄☂🌧☂❄ Table with a winter-themed separator. Quite Ugly. ❄☂🌧☂❄
❄☂🌧☂❄ˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣ❄☂🌧☂❄ˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣˣ❄☂🌧☂❄
As you can see, the new layout and its description were added the output of builtin_layouts()
of the new class.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file nicetable-0.6.0.tar.gz
.
File metadata
- Download URL: nicetable-0.6.0.tar.gz
- Upload date:
- Size: 20.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f47cb05f0b7c962956069fd7273c7da9b5f5c8a2b819615a61d064fca679a928 |
|
MD5 | 3e6c12f88cc37b3cbdf1a759bc169b93 |
|
BLAKE2b-256 | 34e3d83dffa67cd77343060250f1edf543178044b0f2d0afeac3851fa72a2456 |
File details
Details for the file nicetable-0.6.0-py3-none-any.whl
.
File metadata
- Download URL: nicetable-0.6.0-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.21.0 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3d36dddce0d2856f2640dfe2f2ed2f482625e6ab96058f84b71d7e52467c3cca |
|
MD5 | 24d0df302f12f32d63e8542f76a4f0ba |
|
BLAKE2b-256 | b5b65679afb52f98c11c4cfac9e9e0e1ecbdb46d89dd31e087dbf48559ace28c |