Skip to main content

How to Generate ASCII Tables Using PrettyTable in Python

When building CLI tools, debugging scripts, or displaying structured data in the terminal, a well-formatted table is far easier to read than raw print statements. PrettyTable is a lightweight Python library that generates clean, formatted ASCII tables with minimal effort. It supports sorting, filtering, alignment control, and can even output tables as HTML.

This guide covers installation, data insertion, formatting, and advanced features to help you create professional-looking tables in your Python applications.

Installation

PrettyTable is available via pip:

pip install prettytable

Then import it in your script:

from prettytable import PrettyTable

Creating a Table and Inserting Data

PrettyTable supports two primary ways to add data: row by row or column by column.

Adding Data Row by Row

Set the column headers using field_names, then add each row with add_row():

from prettytable import PrettyTable

table = PrettyTable()

table.field_names = ["Name", "Role", "Salary", "City"]
table.add_row(["Alice", "Engineer", 95000, "New York"])
table.add_row(["Bob", "Designer", 82000, "San Francisco"])
table.add_row(["Charlie", "Manager", 105000, "Chicago"])
table.add_row(["Diana", "Analyst", 78000, "Boston"])
table.add_row(["Eve", "Developer", 91000, "Seattle"])

print(table)

Output:

+---------+-----------+--------+---------------+
| Name | Role | Salary | City |
+---------+-----------+--------+---------------+
| Alice | Engineer | 95000 | New York |
| Bob | Designer | 82000 | San Francisco |
| Charlie | Manager | 105000 | Chicago |
| Diana | Analyst | 78000 | Boston |
| Eve | Developer | 91000 | Seattle |
+---------+-----------+--------+---------------+

Adding Data Column by Column

Use add_column() to add data one column at a time. The first argument is the column name, and the second is a list of values:

from prettytable import PrettyTable

table = PrettyTable()

table.add_column("Name", ["Alice", "Bob", "Charlie", "Diana", "Eve"])
table.add_column("Role", ["Engineer", "Designer", "Manager", "Analyst", "Developer"])
table.add_column("Salary", [95000, 82000, 105000, 78000, 91000])
table.add_column("City", ["New York", "San Francisco", "Chicago", "Boston", "Seattle"])

print(table)

Output:

+---------+-----------+--------+---------------+
| Name | Role | Salary | City |
+---------+-----------+--------+---------------+
| Alice | Engineer | 95000 | New York |
| Bob | Designer | 82000 | San Francisco |
| Charlie | Manager | 105000 | Chicago |
| Diana | Analyst | 78000 | Boston |
| Eve | Developer | 91000 | Seattle |
+---------+-----------+--------+---------------+

This produces the same output as the row-by-row approach.

When to use which method
  • Row by row - best when your data comes in records (e.g., from a database cursor or API response).
  • Column by column - best when your data is organized by field (e.g., separate lists for names, salaries, etc.).

Deleting Data

Deleting Specific Rows

Use del_row(index) to remove a row by its zero-based index:

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Name", "Score"]
table.add_row(["Alice", 95])
table.add_row(["Bob", 82])
table.add_row(["Charlie", 78])
table.add_row(["Diana", 91])

# Remove Bob (index 1)
table.del_row(1)

print(table)

Output:

+---------+-------+
| Name | Score |
+---------+-------+
| Alice | 95 |
| Charlie | 78 |
| Diana | 91 |
+---------+-------+
Index shifts after deletion

After deleting a row, all subsequent row indices shift down by one. If you need to delete multiple rows, delete from highest index to lowest to avoid index errors:

# Correct: delete from bottom up
table.del_row(3)
table.del_row(1)

# Wrong: indices shift after first deletion
# table.del_row(1)
# table.del_row(3) # May be out of range!

Clearing All Data

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Name", "Score"]
table.add_row(["Alice", 95])
table.add_row(["Bob", 82])
table.add_row(["Charlie", 78])
table.add_row(["Diana", 91])

# Remove all rows but keep column headers
table.clear_rows()
print(table)

print()

# Remove everything (rows AND column headers)
table.clear()
print(table)

Output:

+------+-------+
| Name | Score |
+------+-------+
+------+-------+

++
||
++
++

Controlling What Gets Displayed

PrettyTable lets you selectively display specific rows or specific columns without modifying the underlying data.

Selecting Rows

Use the start and end parameters in get_string():

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Name", "Role", "Salary"]
table.add_row(["Alice", "Engineer", 95000])
table.add_row(["Bob", "Designer", 82000])
table.add_row(["Charlie", "Manager", 105000])
table.add_row(["Diana", "Analyst", 78000])
table.add_row(["Eve", "Developer", 91000])

# Display only rows 1 through 3 (indices 1, 2)
print(table.get_string(start=1, end=3))

Output:

+---------+----------+--------+
| Name | Role | Salary |
+---------+----------+--------+
| Bob | Designer | 82000 |
| Charlie | Manager | 105000 |
+---------+----------+--------+

Selecting Columns

Use the fields parameter to choose which columns to display:

print(table.get_string(fields=["Name", "Salary"]))

Output:

+---------+--------+
| Name | Salary |
+---------+--------+
| Alice | 95000 |
| Bob | 82000 |
| Charlie | 105000 |
| Diana | 78000 |
| Eve | 91000 |
+---------+--------+

Sorting Tables

Sort by any column using the sortby property. Use reversesort for descending order:

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Name", "Role", "Salary"]
table.add_row(["Alice", "Engineer", 95000])
table.add_row(["Bob", "Designer", 82000])
table.add_row(["Charlie", "Manager", 105000])
table.add_row(["Diana", "Analyst", 78000])
table.add_row(["Eve", "Developer", 91000])

# Sort by salary ascending
table.sortby = "Salary"
print("Sorted by Salary (ascending):")
print(table)

# Sort by salary descending
table.reversesort = True
print("\nSorted by Salary (descending):")
print(table)

Output:

Sorted by Salary (ascending):
+---------+-----------+--------+
| Name | Role | Salary |
+---------+-----------+--------+
| Diana | Analyst | 78000 |
| Bob | Designer | 82000 |
| Eve | Developer | 91000 |
| Alice | Engineer | 95000 |
| Charlie | Manager | 105000 |
+---------+-----------+--------+

Sorted by Salary (descending):
+---------+-----------+--------+
| Name | Role | Salary |
+---------+-----------+--------+
| Charlie | Manager | 105000 |
| Alice | Engineer | 95000 |
| Eve | Developer | 91000 |
| Bob | Designer | 82000 |
| Diana | Analyst | 78000 |
+---------+-----------+--------+

You can also sort inline using get_string():

print(table.get_string(sortby="Name", reversesort=False))

Customizing Table Appearance

Text Alignment

Control alignment per column using the align property:

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Item", "Quantity", "Price"]
table.add_row(["Laptop", 5, "$1,200"])
table.add_row(["Mouse", 50, "$25"])
table.add_row(["Keyboard", 30, "$75"])

# Set alignment: 'l' = left, 'r' = right, 'c' = center
table.align["Item"] = "l"
table.align["Quantity"] = "r"
table.align["Price"] = "r"

print(table)

Output:

+----------+----------+--------+
| Item | Quantity | Price |
+----------+----------+--------+
| Laptop | 5 | $1,200 |
| Mouse | 50 | $25 |
| Keyboard | 30 | $75 |
+----------+----------+--------+

Changing Table Style

PrettyTable includes several preset styles:

from prettytable import PrettyTable, MARKDOWN, MSWORD_FRIENDLY, PLAIN_COLUMNS

table = PrettyTable()
table.field_names = ["Name", "Score"]
table.add_row(["Alice", 95])
table.add_row(["Bob", 82])

# Markdown-compatible output
table.set_style(MARKDOWN)
print("Markdown style:")
print(table)

# Minimal style without borders
table.set_style(PLAIN_COLUMNS)
print("\nPlain columns style:")
print(table)

Output:

Markdown style:
| Name | Score |
| :---: | :---: |
| Alice | 95 |
| Bob | 82 |

Plain columns style:
Name Score
Alice 95
Bob 82
note

The MARKDOWN style is particularly useful when generating tables for README files, documentation, or Docusaurus content.

Customizing Borders and Padding

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Name", "Score"]
table.add_row(["Alice", 95])
table.add_row(["Bob", 82])

# Adjust padding (space between content and border)
table.padding_width = 3

# Custom border characters
table.junction_char = "+"
table.horizontal_char = "="
table.vertical_char = "‖"

print(table)

Output:

+===========+===========+
‖ Name ‖ Score ‖
+===========+===========+
‖ Alice ‖ 95 ‖
‖ Bob ‖ 82 ‖
+===========+===========+

Generating HTML Output

PrettyTable can export your table as an HTML string, useful for embedding in web pages or reports:

from prettytable import PrettyTable

table = PrettyTable()
table.field_names = ["Name", "Role", "Salary"]
table.add_row(["Alice", "Engineer", 95000])
table.add_row(["Bob", "Designer", 82000])

html = table.get_html_string()
print(html)

Output:

<table>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Engineer</td>
<td>95000</td>
</tr>
<tr>
<td>Bob</td>
<td>Designer</td>
<td>82000</td>
</tr>
</tbody>
</table>

You can add HTML attributes like classes or IDs:

html = table.get_html_string(attributes={"id": "salary-table", "class": "data-table"})

Loading Data from CSV Files

PrettyTable can read data directly from CSV files:

from prettytable import from_csv

with open("employees.csv", "r") as f:
table = from_csv(f)

print(table)

This automatically uses the first row of the CSV as column headers and populates the table with the remaining rows.

Quick Reference

FeatureCode
Create tabletable = PrettyTable()
Set headerstable.field_names = ["A", "B"]
Add rowtable.add_row(["val1", "val2"])
Add columntable.add_column("Name", [values])
Delete rowtable.del_row(index)
Clear rowstable.clear_rows()
Sort ascendingtable.sortby = "Column"
Sort descendingtable.reversesort = True
Select columnstable.get_string(fields=["A"])
Select rowstable.get_string(start=1, end=3)
Set alignmenttable.align["Column"] = "l"
Get HTMLtable.get_html_string()

Conclusion

PrettyTable is a simple yet powerful library for generating formatted ASCII tables in Python. It handles all the tedious work of calculating column widths, aligning text, and drawing borders.

  • Whether you're building CLI tools, generating reports, or simply debugging data in the terminal, PrettyTable gives you clean, professional output with just a few lines of code.
  • Its support for sorting, filtering, custom styling, and HTML export makes it versatile enough for a wide range of applications.