Claude Code for PrettyTable: ASCII Tables in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for PrettyTable: ASCII Tables in Python
AI

Claude Code for PrettyTable: ASCII Tables in Python

Published: March 19, 2028
Read time: 5 min read
By: Claude Skills 360

PrettyTable generates ASCII tables for terminal output from Python data. pip install prettytable. Basic: from prettytable import PrettyTable; t = PrettyTable(["Name", "Age"]). t.add_row(["Alice", 30]). print(t). Bulk: t.add_rows([["Bob",25],["Carol",35]]). Field names: PrettyTable(field_names=["A","B","C"]). Align: t.align["Name"] = "l" — l/r/c per column. t.align = "r" — all. Max width: t.max_width = 30. t._max_width["name"] = 20. Sort: t.sortby = "Age"; t.reversesort = True. Border: t.border = False. Header: t.header = False. Get string: t.get_string(fields=["Name"], start=0, end=5, sortby="Age"). Style: from prettytable import SINGLE_BORDER, DOUBLE_BORDER, MARKDOWN, ORGMODE; t.set_style(MARKDOWN). From CSV: from prettytable import from_csv; t = from_csv(open("f.csv")). From JSON: t = from_json('{"Name":["Alice"],"Age":[30]}'). Cursor: from prettytable import from_db_cursor; t = from_db_cursor(cursor). JSON out: t.get_json_string(). CSV out: t.get_csv_string(). t.get_html_string(). Float: t.float_format = ".2". t.int_format = "08". Claude Code generates prettytable terminal tables, report formatters, and CLI result displayers.

CLAUDE.md for PrettyTable

## PrettyTable Stack
- Version: prettytable >= 3.9 | pip install prettytable
- Create: PrettyTable(["Name", "Age"]) | t.add_row([...]) | t.add_rows([...])
- Align: t.align["col"] = "l"/"r"/"c" | t.align = "r" for all
- Sort: t.sortby = "col" | t.reversesort = True
- Style: t.set_style(MARKDOWN) | SINGLE_BORDER | DOUBLE_BORDER | ORGMODE
- Export: t.get_string() | t.get_csv_string() | t.get_json_string() | get_html_string()
- Import: from_csv(fh) | from_json(json_str) | from_db_cursor(cursor)

PrettyTable Terminal Table Pipeline

# app/tables.py — PrettyTable formatters, DB result display, and pandas integration
from __future__ import annotations

from typing import Any

from prettytable import (
    DOUBLE_BORDER,
    MARKDOWN,
    ORGMODE,
    SINGLE_BORDER,
    PrettyTable,
    from_db_cursor,
)


# ─────────────────────────────────────────────────────────────────────────────
# 1. Table factory helpers
# ─────────────────────────────────────────────────────────────────────────────

def make_table(
    columns: list[str],
    rows: list[list[Any]] | None = None,
    align: str | dict[str, str] = "l",
    max_width: int | None = None,
) -> PrettyTable:
    """
    Create a PrettyTable with sensible defaults.
    align: "l"/"r"/"c" for all columns, or {col: align} per column.
    max_width: truncate all columns wider than this.
    """
    t = PrettyTable(field_names=columns)

    if isinstance(align, dict):
        for col, a in align.items():
            t.align[col] = a
    else:
        t.align = align

    if max_width is not None:
        t.max_width = max_width

    if rows:
        t.add_rows(rows)

    return t


def dict_table(
    data: list[dict[str, Any]],
    columns: list[str] | None = None,
    align: str = "l",
    max_width: int | None = None,
) -> PrettyTable:
    """
    Build a table from a list of dicts.
    columns: explicit column order; defaults to keys of first row.
    """
    if not data:
        return PrettyTable(field_names=columns or [])

    cols = columns or list(data[0].keys())
    rows = [[str(row.get(c, "")) for c in cols] for row in data]
    return make_table(cols, rows, align=align, max_width=max_width)


def markdown_table(
    columns: list[str],
    rows: list[list[Any]],
) -> str:
    """Return a Markdown-formatted table string."""
    t = make_table(columns, rows)
    t.set_style(MARKDOWN)
    return t.get_string()


def bordered_table(
    columns: list[str],
    rows: list[list[Any]],
    double: bool = False,
) -> str:
    """Return a table with single or double line borders."""
    t = make_table(columns, rows)
    t.set_style(DOUBLE_BORDER if double else SINGLE_BORDER)
    return t.get_string()


def org_table(columns: list[str], rows: list[list[Any]]) -> str:
    """Return an Emacs org-mode table string."""
    t = make_table(columns, rows)
    t.set_style(ORGMODE)
    return t.get_string()


# ─────────────────────────────────────────────────────────────────────────────
# 2. Sorted and filtered output
# ─────────────────────────────────────────────────────────────────────────────

def print_sorted(
    t: PrettyTable,
    sort_by: str,
    reverse: bool = False,
    fields: list[str] | None = None,
    limit: int | None = None,
) -> None:
    """Print a subset of a table, sorted by a column."""
    kwargs: dict[str, Any] = {
        "sortby":      sort_by,
        "reversesort": reverse,
    }
    if fields:
        kwargs["fields"] = fields
    if limit is not None:
        kwargs["end"] = limit
    print(t.get_string(**kwargs))


def top_n_table(
    columns: list[str],
    rows: list[list[Any]],
    sort_by: str,
    n: int = 10,
    reverse: bool = True,
) -> str:
    """Return the top-N rows sorted by a numeric column."""
    t = make_table(columns, rows)
    return t.get_string(sortby=sort_by, reversesort=reverse, end=n)


# ─────────────────────────────────────────────────────────────────────────────
# 3. Database cursor helpers
# ─────────────────────────────────────────────────────────────────────────────

def table_from_cursor(cursor) -> PrettyTable:
    """
    Build a PrettyTable directly from a DB-API 2.0 cursor.
    Works with sqlite3, psycopg2, psycopg3, pymysql, etc.
    """
    return from_db_cursor(cursor)


def print_query_result(cursor, max_width: int = 40) -> None:
    """Execute a query and print results as a table."""
    t = from_db_cursor(cursor)
    t.max_width = max_width
    t.align = "l"
    print(t)


def sqlite_query_table(db_path: str, sql: str, params: tuple = ()) -> str:
    """
    Run a SQLite query and return its output as a formatted table string.
    Useful for quick ad-hoc reporting.
    """
    import sqlite3
    with sqlite3.connect(db_path) as conn:
        cur = conn.execute(sql, params)
        t   = from_db_cursor(cur)
    t.align = "l"
    t.max_width = 50
    return t.get_string()


# ─────────────────────────────────────────────────────────────────────────────
# 4. Pandas integration
# ─────────────────────────────────────────────────────────────────────────────

def from_dataframe(
    df,
    columns: list[str] | None = None,
    max_rows: int | None = None,
    max_width: int | None = None,
) -> PrettyTable:
    """
    Create a PrettyTable from a pandas DataFrame.
    columns: which columns to include; defaults to all.
    max_rows: truncate to first max_rows rows.
    """
    cols = columns or list(df.columns)
    data = df[cols]
    if max_rows is not None:
        data = data.head(max_rows)

    rows = data.values.tolist()
    rows = [[str(v) for v in row] for row in rows]
    return make_table(cols, rows, max_width=max_width)


def dataframe_summary_table(df) -> str:
    """
    Generate a summary table for a DataFrame: column name, dtype, non-nulls, unique count.
    """
    rows = []
    for col in df.columns:
        rows.append([
            col,
            str(df[col].dtype),
            str(df[col].notna().sum()),
            str(df[col].nunique()),
            str(df[col].iloc[0]) if len(df) > 0 else "",
        ])
    t = make_table(
        ["Column", "Dtype", "Non-Null", "Unique", "Sample"],
        rows,
        align={"Column": "l", "Dtype": "l", "Non-Null": "r", "Unique": "r", "Sample": "l"},
    )
    return t.get_string()


# ─────────────────────────────────────────────────────────────────────────────
# 5. Export helpers
# ─────────────────────────────────────────────────────────────────────────────

def to_markdown(t: PrettyTable) -> str:
    t.set_style(MARKDOWN)
    return t.get_string()


def to_csv_string(t: PrettyTable) -> str:
    return t.get_csv_string()


def to_html(t: PrettyTable, attributes: dict[str, str] | None = None) -> str:
    attr_str = " ".join(f'{k}="{v}"' for k, v in (attributes or {}).items())
    return t.get_html_string(attributes={"class": "table", **(attributes or {})})


def save_table(t: PrettyTable, path: str, fmt: str = "txt") -> None:
    """Save a table to a file. fmt: 'txt', 'csv', 'html', 'md'."""
    if fmt == "csv":
        content = to_csv_string(t)
    elif fmt == "html":
        content = to_html(t)
    elif fmt == "md":
        content = to_markdown(t)
    else:
        content = t.get_string()
    with open(path, "w", encoding="utf-8") as fh:
        fh.write(content)


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== Basic table ===")
    t = make_table(
        ["Name", "City", "Score", "Active"],
        [
            ["Alice",   "München",  "98.5",  "Yes"],
            ["Bob",     "New York", "87.0",  "Yes"],
            ["Charlie", "Tokyo",    "92.3",  "No"],
            ["Diana",   "London",   "95.1",  "Yes"],
        ],
        align={"Name": "l", "City": "l", "Score": "r", "Active": "c"},
    )
    print(t)

    print("\n=== Sorted top-3 by Score ===")
    print(t.get_string(sortby="Score", reversesort=True, end=3))

    print("\n=== Markdown style ===")
    print(markdown_table(
        ["Package", "Stars", "Description"],
        [
            ["prettytable",  "1.2k", "ASCII table formatting"],
            ["tabulate",     "3.4k", "Table formatting library"],
            ["rich",         "45k",  "Rich text and beautiful formatting"],
        ],
    ))

    print("\n=== Single border ===")
    print(bordered_table(
        ["Host",      "Port", "Status"],
        [["db.prod",  "5432", "UP"],
         ["db.replica","5432","UP"],
         ["redis",    "6379", "DOWN"]],
    ))

    print("\n=== Double border ===")
    print(bordered_table(
        ["Month", "Revenue", "Users"],
        [["Jan", "$12,500", "1,234"],
         ["Feb", "$14,200", "1,567"],
         ["Mar", "$16,800", "1,890"]],
        double=True,
    ))

    print("\n=== dict_table ===")
    data = [
        {"name": "Alice", "score": 98, "rank": 1},
        {"name": "Bob",   "score": 87, "rank": 2},
        {"name": "Carol", "score": 92, "rank": 3},
    ]
    print(dict_table(data).get_string(sortby="rank"))

    print("\n=== Export formats ===")
    simple = make_table(["a", "b"], [[1, 2], [3, 4]])
    print(f"CSV: {to_csv_string(simple).strip()!r}")
    print(f"MD:  {to_markdown(simple).strip()!r}")

For the tabulate alternative — tabulate is similar in purpose (ASCII table formatting) but returns a string rather than an object, so you can’t modify alignment or sort after construction; PrettyTable provides a mutable object (t.align["col"], t.sortby, t.max_width) and built-in DB cursor and DataFrame ingestion, while tabulate is better when you just need tabulate(data, headers=...) as a one-liner without needing to reconfigure the table. For the rich.table.Table alternative — rich.Table supports ANSI color, live updates, emoji, box styles from a large library, and renders beautifully in supported terminals; PrettyTable targets plain ASCII output that works equally well in logs, files, email bodies, and non-color terminals — choose rich when color is available, PrettyTable when you need portable plain-text output. The Claude Skills 360 bundle includes PrettyTable skill sets covering PrettyTable() constructor, add_row()/add_rows(), align per-column, border/header control, set_style(MARKDOWN/SINGLE_BORDER/DOUBLE_BORDER/ORGMODE), get_string() with sortby/fields/start/end, from_db_cursor() for DB results, dict_table() helper, from_dataframe() pandas integration, dataframe_summary_table() column profiler, markdown_table()/bordered_table() convenience wrappers, and export to CSV/HTML/Markdown. Start with the free tier to try ASCII table formatting code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free