Inspect notebook data
A displayed view exposes data, files, and graph namespaces through anywidget.
This route uses the base package and does not require Deno.
Display a notebook
In Jupyter, display the view first:
import observablejs as obs
notebook = obs.Notebook(
obs.ojs("rows = [{amount: 2}, {amount: 4}, {amount: 6}]", key="rows"),
obs.ojs("total = rows.reduce((sum, row) => sum + row.amount, 0)", key="total"),
)
view = notebook.view("total", capture_state=False)
view
The view displays 12. It evaluates rows as a hidden dependency. Preview
capture is optional for namespace reads and dataset discovery.
Inspect source and dependencies
Cell handles and source are available immediately:
print(notebook.cells["rows"].source)
print(notebook.cells.keys())
After display, ask the originating browser for its analysis:
names = await view.data.names()
graph = await view.graph.snapshot()
upstream = await view.graph.upstream("total")
The graph describes the full definition. Reading it does not execute additional
cells or fetch imports. view.inspection is the latest readonly analysis snapshot
for traitlets observers and starts as None before publication.
Read a hidden dependency
Run this in a later Jupyter cell:
rows = await view.data["rows"].to_python()
print(rows)
[{'amount': 2}, {'amount': 4}, {'amount': 6}]
The method waits for the requested value and returns detached Python data. It reads this view's current browser values, including browser interactions.
Use a target library directly when you need a dataframe:
frame = await view.data["rows"].to_polars(columns=["amount"], limit=2)
table = await view.data["rows"].to_arrow()
Install Polars or PyArrow for the corresponding conversion. Projection and row ranges reduce transfer volume before conversion.
Discover datasets
catalog = await view.data.discover()
for dataset in catalog.datasets:
print(dataset.name, await dataset.describe())
frame = await catalog.datasets["rows"].to_polars()
catalog.errors reports failures while retaining independent datasets.
catalog.pending marks incomplete evaluation. Discovered references pin the
observed value revision. Get a new catalog when a value changes.
For passive reactive observation, view.datasets publishes the latest readonly
metadata tuple. Inspect that trait directly or observe it with traitlets. In
marimo, view.value subscribes a cell to frontend updates.
Run full reads in marimo
An executing marimo cell blocks browser response processing. Launch the read in a background coroutine so the cell can finish and the browser can reply:
import asyncio
import marimo as mo
import observablejs as obs
notebook = obs.Notebook(
obs.ojs("rows = [{amount: 2}, {amount: 4}, {amount: 6}]", key="rows"),
)
view = notebook.view(capture_state=False)
get_rows, set_rows = mo.state(None)
async def collect_rows():
rows = await view.data["rows"].to_python()
set_rows(rows)
read_task = asyncio.create_task(collect_rows())
view
Display the result in another cell:
rows = get_rows()
mo.ui.table(rows) if rows is not None else mo.md("Loading data")
Keep read_task to cancel outstanding work. view.close() also ends pending
requests. Exceptions should be handled in the coroutine when the UI needs to
show an error state.
Read original files
raw = await view.files["sales.csv"].read_bytes()
frame = await view.files["sales.csv"].to_polars()
These methods use the view's browser URL resolution and credentials. Reading
view.data[name] evaluates the producing code and its transformations instead.
For synchronous Python scripts, use headless notebook data. See the namespace reference for descriptions, provenance, conversion options, and async headless access.