Python SDK

The witan PyPI package installs the Witan CLI and a typed Python SDK. The SDK opens a witan xlsx rpc subprocess, keeps a workbook session alive, and exposes the same spreadsheet operations as witan xlsx exec with Pythonic snake_case method names.

Use the SDK when your application is already Python and needs repeated reads, writes, searches, recalculation, rendering, or linting against the same workbook.

For the full method list, signatures, and return shapes, see the xlsx API.

Install

pip install witan

For one-shot CLI use without a persistent install, use uvx witan. For SDK imports, install the package into your Python environment.

Open a workbook

from witan import Workbook

with Workbook("report.xlsx") as wb:
    sheets = wb.list_sheets()
    tsv = wb.read_range_tsv("Summary!A1:F20")

print([sheet["sheet"] for sheet in sheets])
print(tsv)

The context manager closes the subprocess automatically. In notebooks or REPLs, use explicit close:

from witan import Workbook

wb = Workbook("report.xlsx")
try:
    tsv = wb.read_range_tsv("Summary!A1:F20")
finally:
    wb.close()

Create and save

from witan import Workbook

with Workbook("model.xlsx", create=True) as wb:
    wb.add_sheet("Inputs")
    result = wb.set_cells([
        {"address": "Inputs!A1", "value": "Revenue"},
        {"address": "Inputs!B1", "value": 1250000},
        {"address": "Inputs!C1", "formula": "=B1*1.1", "value": None},
    ])

    if result["errors"]:
        raise RuntimeError(result["errors"])

    wb.save()

Writes update the live workbook session and recalculate dependent formulas. Call save() when you want to write the workbook bytes back to disk.

Async sessions

Use AsyncWorkbook in asyncio services, notebooks, and concurrent workflows:

from witan import AsyncWorkbook

async with AsyncWorkbook("report.xlsx") as wb:
    cell = await wb.read_cell("Summary!A1")
    lint = await wb.lint(range_addresses=["Summary!A1:F20"])

print(cell["text"], lint["total"])

In Jupyter/IPython, top-level await works with explicit close:

from witan import AsyncWorkbook

wb = AsyncWorkbook("report.xlsx")
cell = await wb.read_cell("Summary!A1")
await wb.close()

Common workflows

from witan import Workbook, Regex

with Workbook("report.xlsx") as wb:
    sheets = wb.list_sheets()
    cell = wb.read_cell("Summary!B5")
    rows = wb.read_range_tsv("Summary!A1:F20")
    matches = wb.find_cells(Regex(r"revenue|ebitda", "i"), in_="Summary!A:Z")

Use read_range_tsv, read_row_tsv, and read_column_tsv when passing workbook data to a language model. TSV is usually smaller and easier to scan than nested JSON.

Edit and verify

with Workbook("report.xlsx") as wb:
    before = wb.preview_styles("Summary!A1:F20")

    result = wb.set_cells([
        {"address": "Summary!B5", "formula": "=SUM(Revenue!B2:B13)", "value": None}
    ])
    lint = wb.lint(range_addresses=["Summary!A1:F20"])
    after = wb.preview_styles("Summary!A1:F20")

    if result["errors"] or lint["total"]:
        raise RuntimeError({"formula_errors": result["errors"], "lint": lint})

    wb.save()

preview_styles() returns a data:image/...;base64,... URL for the rendered range. For command-line image files and pixel diffs, use witan xlsx render.

Trace and run sweeps

with Workbook("model.xlsx") as wb:
    inputs = wb.trace_to_inputs("Summary!F25")
    sweep = wb.sweep_inputs(
        [{"address": "Inputs!B5", "values": [0.02, 0.04, 0.06]}],
        ["Summary!F25"],
        mode="cartesian",
        include_stats=True,
    )

print(sweep["tsv"])

API reference

The Python SDK follows the same xlsx API as witan xlsx exec, with snake_case method names. See xlsx API for the full method list, signatures, and return shapes across Python, JavaScript, and xlsx exec.

Options

Pass options when opening the workbook:

wb = Workbook(
    "report.xlsx",
    locale="en-US",
    stateless=True,
    api_key="sk_...",
    api_url="https://api.witanlabs.com",
    request_timeout=60,
)

Most configuration can also come from environment variables. See CLI Reference.

Errors

from witan import Workbook, WitanRPCError, WitanProcessError, WitanTimeoutError

try:
    with Workbook("report.xlsx") as wb:
        wb.read_range("InvalidRange!!!")
except WitanTimeoutError as exc:
    print("request timed out", exc)
except WitanRPCError as exc:
    print("RPC error", exc)
except WitanProcessError as exc:
    print("process error", exc)

Next steps

  • xlsx API — full method signatures and return shapes.
  • JavaScript SDK — use the same xlsx API from Node.js.
  • CLI Scripting — run one-off workbook scripts with witan xlsx exec.
  • Concepts — understand the shared workbook model underneath every SDK.