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.
- 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 |
+---------+-------+
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
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
| Feature | Code |
|---|---|
| Create table | table = PrettyTable() |
| Set headers | table.field_names = ["A", "B"] |
| Add row | table.add_row(["val1", "val2"]) |
| Add column | table.add_column("Name", [values]) |
| Delete row | table.del_row(index) |
| Clear rows | table.clear_rows() |
| Sort ascending | table.sortby = "Column" |
| Sort descending | table.reversesort = True |
| Select columns | table.get_string(fields=["A"]) |
| Select rows | table.get_string(start=1, end=3) |
| Set alignment | table.align["Column"] = "l" |
| Get HTML | table.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.