Welcome to beautifultable’s documentation!

https://badge.fury.io/py/beautifultable.svg https://img.shields.io/pypi/pyversions/beautifultable.svg https://codecov.io/gh/pri22296/beautifultable/branch/master/graphs/badge.svg https://api.codacy.com/project/badge/Grade/7a76eb35ad4e450eaf00339e98381511 https://travis-ci.org/pri22296/beautifultable.svg?branch=master Documentation Status https://img.shields.io/badge/Donate-PayPal-yellow.svg

Introduction

This Package provides BeautifulTable class for easily printing tabular data in a visually appealing ASCII format to a terminal.

Features included but not limited to:

  • Full customization of the look and feel of the table
  • Build the Table as you wish, By adding rows, or by columns or even mixing both these approaches.
  • Full support for colors using ANSI sequences or any library of your choice. It just works.
  • Plenty of predefined styles for multiple use cases and option to create custom ones.
  • Support for Unicode characters.

Contents

Installation

pip install beautifultable

Quickstart

Building the Table

Building a table is very easy. You can append rows and columns in the table. Let’s create our first BeautifulTable.

>>> from beautifultable import BeautifulTable
>>> table = BeautifulTable()
>>> table.column_headers = ["name", "rank", "gender"]
>>> table.append_row(["Jacob", 1, "boy"])
>>> table.append_row(["Isabella", 1, "girl"])
>>> table.append_row(["Ethan", 2, "boy"])
>>> table.append_row(["Sophia", 2, "girl"])
>>> table.append_row(["Michael", 3, "boy"])
>>> print(table)
+----------+------+--------+
|   name   | rank | gender |
+----------+------+--------+
|  Jacob   |  1   |  boy   |
+----------+------+--------+
| Isabella |  1   |  girl  |
+----------+------+--------+
|  Ethan   |  2   |  boy   |
+----------+------+--------+
|  Sophia  |  2   |  girl  |
+----------+------+--------+
| Michael  |  3   |  boy   |
+----------+------+--------+

We created our first table. Let’s add some more data to it. But this time we will add a new column.

>>> table.append_column("year", ["2010", "2012", "2008", "2010", "2011"])
>>> print(table)
+----------+------+--------+------+
|   name   | rank | gender | year |
+----------+------+--------+------+
|  Jacob   |  1   |  boy   | 2010 |
+----------+------+--------+------+
| Isabella |  1   |  girl  | 2012 |
+----------+------+--------+------+
|  Ethan   |  2   |  boy   | 2008 |
+----------+------+--------+------+
|  Sophia  |  2   |  girl  | 2010 |
+----------+------+--------+------+
| Michael  |  3   |  boy   | 2011 |
+----------+------+--------+------+

You can also build a BeautifulTable using slicing. Slicing creates a new table with it’s own copy of data. But it retains the properties of the original object.

>>> new_table = table[:3]
>>> print(new_table)
+----------+------+--------+------+
|   name   | rank | gender | year |
+----------+------+--------+------+
|  Jacob   |  1   |  boy   | 2010 |
+----------+------+--------+------+
| Isabella |  1   |  girl  | 2012 |
+----------+------+--------+------+
|  Ethan   |  2   |  boy   | 2008 |
+----------+------+--------+------+

As you can see how easy it is to create a Table with beautifultable. Now lets move on to see some common use cases. Note that not all features are described here. See the API Documentation to get a detailed look at all the features.

Accessing Rows

You can access a row using it’s index. It works just like a python list. It returns a RowData object.

>>> print(list(table[3]))
['Sophia', 2, 'girl', '2010']

To access a particular field of a row, you can use the index, or the header.

>>> print(table[3][2])
girl
>>> print(table[3]['gender'])
girl

Accessing Columns

Columns can be accessed using their header names or their index. But since name of headers can be duplicated, There are methods provided to access columns using their index. If columns are accessed using their names, and if more than one column exists with that name as it’s header, then the first column found would be returned.

It should be noted here that the returned column is not a list. It is an iterator.

>>> print(list(table['name']))
['Jacob', 'Isabella', 'Ethan', 'Sophia', 'Michael']

Counting Rows and Columns

You can get the number of columns in the table by accessing the column_count property.

>>> print(table.column_count)
3

To get the number of rows, you can just use the len function.

>>> print(len(table))
5

Inserting Rows and Columns

BeautifulTable provides 2 methods, insert_row() and insert_column() for this purpose.

>>> table.insert_row(3, ['Gary', 2, 'boy', 2009])
>>> table.insert_column(2, 'marks', [78, 67, 82, 56, 86, 74])
>>> print(table)
+----------+------+-------+--------+------+
|   name   | rank | marks | gender | year |
+----------+------+-------+--------+------+
|  Jacob   |  1   |  78   |  boy   | 2010 |
+----------+------+-------+--------+------+
| Isabella |  1   |  67   |  girl  | 2012 |
+----------+------+-------+--------+------+
|  Ethan   |  2   |  82   |  boy   | 2008 |
+----------+------+-------+--------+------+
|   Gary   |  2   |  56   |  boy   | 2009 |
+----------+------+-------+--------+------+
|  Sophia  |  2   |  86   |  girl  | 2010 |
+----------+------+-------+--------+------+
| Michael  |  3   |  74   |  boy   | 2011 |
+----------+------+-------+--------+------+

Removing Rows and Columns

Removing a row or column is very easy. Just delete it using del statement.

>>> del table[3]
>>> del table['year']
>>> print(table)
+----------+------+-------+--------+
|   name   | rank | marks | gender |
+----------+------+-------+--------+
|  Jacob   |  1   |  78   |  boy   |
+----------+------+-------+--------+
| Isabella |  1   |  67   |  girl  |
+----------+------+-------+--------+
|  Ethan   |  2   |  82   |  boy   |
+----------+------+-------+--------+
|  Sophia  |  2   |  86   |  girl  |
+----------+------+-------+--------+
| Michael  |  3   |  74   |  boy   |
+----------+------+-------+--------+

You can also use the helper methods pop_row(), pop_column() to do the same thing. Both these methods take the index of the row, or column to be removed.

Instead of the index, you can also pass the header of the column to pop_column(). Therefore the following 2 snippets are equivalent.

>>> table.pop_column('marks')
>>> table.pop_column(2)

Updating data in the Table

Let’s change the name in the 4th row to 'Sophie'.

>>> table[3][0] = 'Sophie' # index of 4th row is 3
>>> print(table[3])
['Sophie', 2, 86, 'girl']

You could have done the same thing using the header.

>>> table[3]['name'] = 'Sophie'

Or, you can also change the entire row, or even multiple rows using slicing.

>>> table[3] = ['Sophie', 2, 56, 'girl']

You can also update existing columns as shown below.

>>> table['marks'] = [75, 46, 89, 56, 82]
>>> print(table)
+----------+------+-------+--------+
|   name   | rank | marks | gender |
+----------+------+-------+--------+
|  Jacob   |  1   |  75   |  boy   |
+----------+------+-------+--------+
| Isabella |  1   |  46   |  girl  |
+----------+------+-------+--------+
|  Ethan   |  2   |  89   |  boy   |
+----------+------+-------+--------+
|  Sophie  |  2   |  56   |  girl  |
+----------+------+-------+--------+
| Michael  |  3   |  82   |  boy   |
+----------+------+-------+--------+

The methods update_row() and update_column() can be used to perform the operations discussed in this section.

Note that you can only update existing columns but can’t create a new column using this method. For that you need to use the methods append_column() or insert_column().

Searching for rows or columns headers

Cheking if a header is in the table.

>>> 'rank' in table
True

Cheking if a row is in table

>>> ["Ethan", 2, 89, "boy"] in table
True

Sorting based on a Column

You can also sort() the table based on a column by specifying it’s index or it’s header.

>>> table.sort('name')
>>> print(table)
+----------+------+-------+--------+
|   name   | rank | marks | gender |
+----------+------+-------+--------+
|  Ethan   |  2   |  89   |  boy   |
+----------+------+-------+--------+
| Isabella |  1   |  46   |  girl  |
+----------+------+-------+--------+
|  Jacob   |  1   |  75   |  boy   |
+----------+------+-------+--------+
| Michael  |  3   |  82   |  boy   |
+----------+------+-------+--------+
|  Sophie  |  2   |  56   |  girl  |
+----------+------+-------+--------+

Customizing the look of the Table

Alignment

Let’s change the way some columns are aligned in our table.

>>> table.column_alignments['name'] = BeautifulTable.ALIGN_LEFT
>>> table.column_alignments['gender'] = BeautifulTable.ALIGN_RIGHT
>>> print(table)
+----------+------+--------+------+
| name     | rank | gender | year |
+----------+------+--------+------+
| Jacob    |  1   |    boy | 2010 |
+----------+------+--------+------+
| Isabella |  1   |   girl | 2012 |
+----------+------+--------+------+
| Ethan    |  2   |    boy | 2008 |
+----------+------+--------+------+
| Sophia   |  2   |   girl | 2010 |
+----------+------+--------+------+
| Michael  |  3   |    boy | 2011 |
+----------+------+--------+------+
Padding

You can change the padding for individual column similar to the alignment.

>>> table.left_padding_widths['rank'] = 5
>>> table.right_padding_widths['rank'] = 3
>>> print(table)
+----------+------------+--------+------+
| name     |     rank   | gender | year |
+----------+------------+--------+------+
| Jacob    |      1     |    boy | 2010 |
+----------+------------+--------+------+
| Isabella |      1     |   girl | 2012 |
+----------+------------+--------+------+
| Ethan    |      2     |    boy | 2008 |
+----------+------------+--------+------+
| Sophia   |      2     |   girl | 2010 |
+----------+------------+--------+------+
| Michael  |      3     |    boy | 2011 |
+----------+------------+--------+------+

You can use a helper method set_padding_widths() to set the left and right padding to a common value.

Styling

beautifultable comes with several predefined styles for various use cases. You can use the set_style() method to set the style of the table. The following styles are available:

  • STYLE_DEFAULT

    >>> table.set_style(BeautifulTable.STYLE_DEFAULT)
    >>> print(table)
    +----------+------+--------+
    |   name   | rank | gender |
    +----------+------+--------+
    |  Jacob   |  1   |  boy   |
    +----------+------+--------+
    | Isabella |  1   |  girl  |
    +----------+------+--------+
    |  Ethan   |  2   |  boy   |
    +----------+------+--------+
    |  Sophia  |  2   |  girl  |
    +----------+------+--------+
    | Michael  |  3   |  boy   |
    +----------+------+--------+
    
  • STYLE_NONE

    >>> table.set_style(BeautifulTable.STYLE_NONE)
    >>> print(table)
       name    rank  gender
      Jacob     1     boy
     Isabella   1     girl
      Ethan     2     boy
      Sophia    2     girl
     Michael    3     boy
    
  • STYLE_DOTTED

    >>> table.set_style(BeautifulTable.STYLE_DOTTED)
    >>> print(table)
    ............................
    :   name   : rank : gender :
    ............................
    :  Jacob   :  1   :  boy   :
    : Isabella :  1   :  girl  :
    :  Ethan   :  2   :  boy   :
    :  Sophia  :  2   :  girl  :
    : Michael  :  3   :  boy   :
    ............................
    
  • STYLE_SEPARATED

    >>> table.set_style(BeautifulTable.STYLE_SEPARATED)
    >>> print(table)
    +==========+======+========+
    |   name   | rank | gender |
    +==========+======+========+
    |  Jacob   |  1   |  boy   |
    +----------+------+--------+
    | Isabella |  1   |  girl  |
    +----------+------+--------+
    |  Ethan   |  2   |  boy   |
    +----------+------+--------+
    |  Sophia  |  2   |  girl  |
    +----------+------+--------+
    | Michael  |  3   |  boy   |
    +----------+------+--------+
    
  • STYLE_COMPACT

    >>> table.set_style(BeautifulTable.STYLE_COMPACT)
    >>> print(table)
       name     rank   gender
    ---------- ------ --------
      Jacob      1      boy
     Isabella    1      girl
      Ethan      2      boy
      Sophia     2      girl
     Michael     3      boy
    
  • STYLE_MYSQL

    >>> table.set_style(BeautifulTable.STYLE_MYSQL)
    >>> print(table)  # Yes, the default style is same as this style
    +----------+------+--------+
    |   name   | rank | gender |
    +----------+------+--------+
    |  Jacob   |  1   |  boy   |
    +----------+------+--------+
    | Isabella |  1   |  girl  |
    +----------+------+--------+
    |  Ethan   |  2   |  boy   |
    +----------+------+--------+
    |  Sophia  |  2   |  girl  |
    +----------+------+--------+
    | Michael  |  3   |  boy   |
    +----------+------+--------+
    
  • STYLE_MARKDOWN

    >>> table.set_style(BeautifulTable.STYLE_MARKDOWN)
    >>> print(table)  # Markdown alignment not supported currently
    |   name   | rank | gender |
    |----------|------|--------|
    |  Jacob   |  1   |  boy   |
    | Isabella |  1   |  girl  |
    |  Ethan   |  2   |  boy   |
    |  Sophia  |  2   |  girl  |
    | Michael  |  3   |  boy   |
    
  • STYLE_RST

    >>> table.set_style(BeautifulTable.STYLE_RST)
    >>> print(table)
    ========== ====== ========
       name     rank   gender
    ========== ====== ========
      Jacob      1      boy
     Isabella    1      girl
      Ethan      2      boy
      Sophia     2      girl
     Michael     3      boy
    ========== ====== ========
    
  • STYLE_BOX

    >>> table.set_style(BeautifulTable.STYLE_BOX)
    >>> print(table)
    ┌──────────┬──────┬────────┐
    │   name   │ rank │ gender │
    ├──────────┼──────┼────────┤
    │  Jacob   │  1   │  boy   │
    ├──────────┼──────┼────────┤
    │ Isabella │  1   │  girl  │
    ├──────────┼──────┼────────┤
    │  Ethan   │  2   │  boy   │
    ├──────────┼──────┼────────┤
    │  Sophia  │  2   │  girl  │
    ├──────────┼──────┼────────┤
    │ Michael  │  3   │  boy   │
    └──────────┴──────┴────────┘
    
  • STYLE_BOX_DOUBLED

    >>> table.set_style(BeautifulTable.STYLE_BOX_DOUBLED)
    >>> print(table)
    ╔══════════╦══════╦════════╗
    ║   name   ║ rank ║ gender ║
    ╠══════════╬══════╬════════╣
    ║  Jacob   ║  1   ║  boy   ║
    ╠══════════╬══════╬════════╣
    ║ Isabella ║  1   ║  girl  ║
    ╠══════════╬══════╬════════╣
    ║  Ethan   ║  2   ║  boy   ║
    ╠══════════╬══════╬════════╣
    ║  Sophia  ║  2   ║  girl  ║
    ╠══════════╬══════╬════════╣
    ║ Michael  ║  3   ║  boy   ║
    ╚══════════╩══════╩════════╝
    
  • STYLE_BOX_ROUNDED

    >>> table.set_style(BeautifulTable.STYLE_BOX_ROUNDED)
    >>> print(table)
    ╭──────────┬──────┬────────╮
    │   name   │ rank │ gender │
    ├──────────┼──────┼────────┤
    │  Jacob   │  1   │  boy   │
    ├──────────┼──────┼────────┤
    │ Isabella │  1   │  girl  │
    ├──────────┼──────┼────────┤
    │  Ethan   │  2   │  boy   │
    ├──────────┼──────┼────────┤
    │  Sophia  │  2   │  girl  │
    ├──────────┼──────┼────────┤
    │ Michael  │  3   │  boy   │
    ╰──────────┴──────┴────────╯
    
  • STYLE_GRID

    >>> table.set_style(BeautifulTable.STYLE_GRID)
    >>> print(table)
    ╔══════════╤══════╤════════╗
    ║   name   │ rank │ gender ║
    ╟──────────┼──────┼────────╢
    ║  Jacob   │  1   │  boy   ║
    ╟──────────┼──────┼────────╢
    ║ Isabella │  1   │  girl  ║
    ╟──────────┼──────┼────────╢
    ║  Ethan   │  2   │  boy   ║
    ╟──────────┼──────┼────────╢
    ║  Sophia  │  2   │  girl  ║
    ╟──────────┼──────┼────────╢
    ║ Michael  │  3   │  boy   ║
    ╚══════════╧══════╧════════╝
    

For more finer customization, you can change what characters are used to draw various parts of the table. Here we show you an example of how you can use this feature. You can read the API Reference for more details.

>>> table.set_style(BeautifulTable.STYLE_NONE)  # clear all formatting
>>> table.left_border_char = 'o'
>>> table.right_border_char = 'o'
>>> table.top_border_char = '<~>'
>>> table.bottom_border_char = '='
>>> table.header_separator_char = '^'
>>> table.column_separator_char = ':'
>>> table.row_separator_char = '~'
>>> print(table)
<~><~><~><~><~><~><~><~><~><
o   name   : rank : gender o
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
o  Jacob   :  1   :  boy   o
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
o Isabella :  1   :  girl  o
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
o  Ethan   :  2   :  boy   o
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
o  Sophia  :  2   :  girl  o
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
o Michael  :  3   :  boy   o
============================

As you can see, you can change quite a lot about your BeautifulTable instance. For further sections, We switch the look of the table to default again.

Colored Tables

beautifultable comes with out of the box support for colored tables using ansi escape sequences. You can also use any library which makes use of these sequences to produce colored text output.

>>> table.append_row([colored("John", 'red'), 4, colored("boy", 'blue')])
>>> print(table)

+----------+------+--------+
|   name   | rank | gender |
+----------+------+--------+
|  Jacob   |  1   |  boy   |
+----------+------+--------+
| Isabella |  1   |  girl  |
+----------+------+--------+
|  Ethan   |  2   |  boy   |
+----------+------+--------+
|  Sophia  |  2   |  girl  |
+----------+------+--------+
| Michael  |  3   |  boy   |
+----------+------+--------+
|   John   |  4   |  boy   |
+----------+------+--------+

You can also use these sequences for making texts bold, italics, etc.

Paragraphs

A cell can contain multiple paragraphs such that each one start from a new line. beautifultable parses \n as a paragraph change.

>>> new_table = BeautifulTable(max_width=40)
>>> new_table.column_headers = ["Heading 1", "Heading 2"]
>>> new_table.append_row(["first Line\nsecond Line", "single line"])
>>> new_table.append_row(["first Line\nsecond Line\nthird Line", "first Line\nsecond Line"])
>>> new_table.append_row(["single line", "this is a very long first line\nThis is a very long second line"])
>>> print(new_table)
+-------------+------------------------+
|  Heading 1  |       Heading 2        |
+-------------+------------------------+
| first Line  |      single line       |
| second Line |                        |
+-------------+------------------------+
| first Line  |       first Line       |
| second Line |      second Line       |
| third Line  |                        |
+-------------+------------------------+
| single line | this is a very long fi |
|             |        rst line        |
|             | This is a very long se |
|             |       cond line        |
+-------------+------------------------+
Subtables

You can even render a BeautifulTable instance inside another table. To do that, just pass the table as any regular text and it just works.

>>> subtable = BeautifulTable()
>>> subtable.column_headers = ["name", "rank", "gender"]
>>> subtable.append_row(["Jacob", 1, "boy"])
>>> subtable.append_row(["Isabella", 1, "girl"])
>>> parent_table = BeautifulTable()
>>> parent_table.column_headers = ["Heading 1", "Heading 2"]
>>> parent_table.append_row(["Sample text", "Another sample text"])
>>> parent_table.append_row([subtable, "More sample text"])
>>> print(parent_table)
+------------------------------+---------------------+
|          Heading 1           |      Heading 2      |
+------------------------------+---------------------+
|         Sample text          | Another sample text |
+------------------------------+---------------------+
| +----------+------+--------+ |  More sample text   |
| |   name   | rank | gender | |                     |
| +----------+------+--------+ |                     |
| |  Jacob   |  1   |  boy   | |                     |
| +----------+------+--------+ |                     |
| | Isabella |  1   |  girl  | |                     |
| +----------+------+--------+ |                     |
+------------------------------+---------------------+

Support for Multibyte Unicode characters

beautifultable comes with in-built support for multibyte unicode such as east-asian characters. To enable support, You need to install the wcwidth library from PyPI.

pip install wcwidth

You can do much more with BeautifulTable but this much should give you a good start. Those of you who are interested to have more control can read the API Documentation.

Changelog

Unreleased

v0.8.0

  • Dropped support for Python 3.3
  • Added support for streaming tables using a generator for cases where data retrieval is slow
  • Alignment, padding, width can now be set for all columns using a simplified syntax like table.column_alignments = beautifultable.ALIGN_LEFT

v0.7.0

  • Added 4 new styles, STYLE_BOX, STYLE_BOX_DOUBLED, STYLE_BOX_ROUNDED, STYLE_GRID.
  • Renamed STYLE_RESTRUCTURED_TEXT to STYLE_RST
  • wcwidth is now an optional dependency
  • Updated the algorithm for calculating width of columns(better division of space among columns)
  • Added support for Paragraphs(using \n character)
  • Added finer control for intersection characters using 12 new attributes intersect_{top|header|row|bottom}_{left|mid|right}
  • Added the ability to also accept bytestrings instead of unicode
  • Deprecated attribute intersection_char
  • Deprecated methods get_top_border(), get_bottom_border(), get_header_separator(), get_row_separator(), auto_calculate_width()
  • Fixed an issue with WEP_ELLIPSIS and WEP_STRIP when using multibyte characters
  • Fixed an issue where table would not be in proper form if column_width is too low

v0.6.0

  • Added support for handling Multi byte strings
  • Added support for colored strings using ANSI escape sequences
  • Added constraint where all strings must be unicode
  • Fixed an issue where sometimes width was calculated as higher than intended

v0.5.3

  • Added support for handing color codes using ANSI escape sequences(experimental)
  • Fixed collections ABCs deprecation warning

v0.5.2

  • Added new style STYLE_NONE
  • Fixed issue regarding improper conversion of non-string floats

v0.5.1

  • Added detect_numerics boolean for toggling automatic numeric conversion

v0.5.0

  • Added new property serialno_header
  • Deprecated methods with misspelled “seperator” in their name.
  • Fixed an issue where table was corrupted when column_count was too high

v0.4.0

  • Added predefined styles for easier customization
  • Added reverse argument to sort() method
  • Fixed enum34 dependency for python versions prior to 3.4

v0.3.0

  • Added property serialno for auto printing serial number
  • Fixed an issue with sign_mode related to str conversion
  • Fixed bugs related to python version prior to 3.3
  • Fixed exception on WEP_ELLIPSIS and token length less than 3
  • Fixed printing issues with empty table

v0.2.0

  • Added python 2 support

v0.1.3

  • Fixed minor issues

v0.1.2

  • Added new property default_padding
  • Added new method update_row
  • Fixed an issue in auto_calculate_width()

v0.1.1

  • Initial release on PyPI

Donation

Love beautifultable? Consider supporting the development :)

https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif