mrkeyoor.com_
Sat 08 Aug 20:58 UTC
PyPIUtilsupdated 08 Aug 2026

texttable

texttable builds plain-text tables from Python rows. You can set headers, column widths, horizontal and vertical alignment, numeric formatting, precision, border characters, and which lines are drawn, then call draw to receive one complete string. Cells may contain newlines and tabs, and optional cjkwrap or wcwidth installations improve CJK and emoji width handling. It is a compact terminal-report formatter, not an interactive widget, streaming renderer, rich terminal framework, or exporter for Markdown, HTML, CSV, or spreadsheets.

Verdict

Still a fine tiny formatter for stable, small ASCII reports. New CLI applications that need rich output or multiple export formats should start with Rich, tabulate, or PrettyTable instead.

API stability5/5Texttable's constructor, add_row, add_rows, header, draw, reset, set_cols_align, set_cols_valign, set_cols_width, set_cols_dtype, set_chars, set_deco, set_max_width, and set_precision have remained recognizable for many years. Version 1.7 only added the boolean datatype marker. That maturity makes existing integrations predictable, although the absence of a declared Python floor and modern type declarations shifts some compatibility checking to users.
Docs2/5The README includes two useful end-to-end examples and a complete pydoc-style list of methods, datatype letters, alignment codes, decoration flags, and defaults. It also calls out optional cjkwrap and wcwidth behavior. However, the presentation still references a Python 2.7 file path, lacks a polished API site, does not explain exception cases or ANSI limitations, and offers little guidance on deterministic Unicode rendering or large tables.
Maintenance2/5The repository is not archived and GitHub reported no open issues or pull requests, but version 1.7.0 was uploaded in October 2023 and the last repository push occurred the same day. The changelog shows a slow cadence of isolated compatibility and formatting fixes, with the last release adding boolean formatting. This can be enough for a finished small library, but it is not evidence of active evolution or rapid support.
Ecosystem3/5Texttable has broad transitive installation volume, an MIT license, no required dependencies, and packages in several Unix distributions. Optional cjkwrap and wcwidth improve difficult terminal-width cases, and latextable exists as a fork for LaTeX output. The ecosystem is otherwise narrow: no official HTML or Markdown renderer, styling layer, terminal abstraction, dataframe adapter, or current typing package is documented.

Use it if

  • You need a small dependency-free ASCII table for logs, tests, reports, or a simple command-line script
  • You want explicit per-column alignment, vertical alignment, width, numeric type, and border control
  • Your table is small enough to build as one string before printing
  • You maintain existing code or a dependency that already uses Texttable's long-stable API
Skip it if

Setup reality

pip install texttable has no required runtime dependencies and imports as from texttable import Texttable. The defaults still carry behavioral choices: max_width is 80, all decorations are enabled, automatic typing can reinterpret numeric-looking values, float precision is 3, and add_rows treats the first row as a header unless header=False. A mismatched header, alignment, width, datatype, or row length can raise ArraySizeError, so determine the schema before adding rows. set_cols_dtype accepts a, t, f, e, i, b, or a callable; use t for identifiers such as ZIP codes and invoice numbers or automatic formatting may strip leading zeros or choose numeric notation. set_cols_width gives exact wrapping widths, while max_width controls the overall table and 0 disables automatic wrapping. Multiline cells are supported and vertical alignment decides where shorter cells sit. Unicode width is environment-sensitive: cjkwrap improves CJK wrapping if installed, and wcwidth improves emoji width if installed, but neither is mandatory, so CI and production can draw differently unless you pin the same extras. The library returns the entire table from draw, which is fine for small reports but duplicates memory and prevents incremental output for large result sets. It also knows nothing about ANSI escape sequences, terminal resizing, sorting, pagination, or safe serialization to other formats. Build plain values first, apply explicit column types and widths, test representative Unicode, and treat styling characters as presentation rather than a machine-readable contract.

Patterns

Build a table with a header and rowsdraw-basic-table

from texttable import Texttable

table = Texttable()
table.header(['Name', 'Age'])
table.add_row(['Ada', 36])
table.add_row(['Grace', 40])
print(table.draw())

draw returns the whole table as a string; print or log it once to avoid adding an extra prefix to every line.

Add a batch without consuming its first row as a headeradd-rows-without-header

table = Texttable()
table.header(['Name', 'Score'])
table.add_rows([['Ada', 98], ['Grace', 95]], header=False)

add_rows defaults header=True, so omitting the flag here would replace the intended first data row with a header.

Set horizontal and vertical alignmentalign-columns

table.set_cols_align(['l', 'r', 'c'])
table.set_cols_valign(['t', 'm', 'b'])

The configuration array must have exactly one entry per column or Texttable raises ArraySizeError.

Control numeric and text formattingformat-column-types

table.set_cols_dtype([
    't',  # preserve identifiers as text
    'i',  # integer
    'f',  # fixed-point float
    'b',  # boolean
])
table.set_precision(2)

Automatic typing can reinterpret numeric strings; mark values such as 00123 as text when leading zeros matter.

Wrap cells at explicit column widthsset-column-widths

table = Texttable(max_width=0)
table.set_cols_width([12, 36, 8])

max_width=0 disables the overall automatic limit, while set_cols_width still wraps each configured column.

Draw only borders and a header separatorchoose-decoration

from texttable import Texttable

table.set_deco(Texttable.BORDER | Texttable.HEADER)

Decoration flags combine with bitwise OR; leaving out VLINES and HLINES removes internal cell and row rules.

Change the four drawing characterscustomize-border-characters

table.set_chars(['-', '|', '+', '='])

The array order is horizontal, vertical, corner, header; multi-column glyphs can break width assumptions.

Use a callable as a column datatypeformat-with-callable

def dollars(value):
    return f'${value:,.2f}'

table.set_cols_dtype(['t', dollars])
table.add_rows([['Item', 'Price'], ['Cable', 12.5]])

The callable must return a string for every value it receives, including any null-like values in your rows.

Reset rows and header before another reportreuse-table

print(table.draw())

table.reset()
table.header(['Key', 'Value'])
table.add_row(['status', 'ok'])

reset clears rows and the header; reapply the next report's schema before adding values.

Catch a mismatched row shapehandle-schema-error

from texttable import ArraySizeError

try:
    table.add_row(['too', 'many', 'cells'])
except ArraySizeError as exc:
    raise ValueError('row does not match table columns') from exc

It is usually better to validate and normalize records before rendering, since one malformed row prevents the final table.

Alternatives

PackageRegistryPick it when
tabulatePyPIYou want many output formats, including Markdown, HTML, grid, and database-style tables
prettytablePyPIYou want a fuller table object with sorting, field selection, and several text or markup styles
richPyPIYou are building a modern terminal UI with color, wrapping, live updates, and console-aware rendering