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.
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
Read and search
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 scenarios
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"])
Method map
The Python SDK follows the xlsx exec API with snake_case names:
| Area | Methods |
|---|---|
| Workbook and sheets | list_sheets, add_sheet, delete_sheet, rename_sheet, get_sheet_properties, set_sheet_properties |
| Reading | read_cell, read_range, read_row, read_column, read_range_tsv, read_row_tsv, read_column_tsv |
| Search | find_cells, find_rows, find_and_replace, describe_sheet, table_lookup |
| Writing | set_cells, copy_range, scale_range, insert_row_after, delete_rows, insert_column_after, delete_columns |
| Formulas | evaluate_formula, evaluate_formulas, get_cell_precedents, get_cell_dependents, trace_to_inputs, trace_to_outputs, sweep_inputs |
| Verification | lint, preview_styles |
| Tables and charts | get_list_object, add_list_object, set_list_object, get_data_table, add_data_table, list_charts, get_chart, add_chart, set_chart |
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 Configuration.
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
- JavaScript SDK — use the same workbook API from Node.js.
- CLI — run one-off workbook scripts with
witan xlsx exec. - Concepts — understand the shared workbook model underneath every SDK.