Skip to main content

Quickstart

Create a reactive notebook in Python, display it in the browser, and read a calculated value back. pyobservablejs supports Python 3.11 through 3.14. Install it in the Python environment used by your notebook:

pip install pyobservablejs

To start a new notebook, uv, a Python environment and package manager, can launch marimo, a reactive Python notebook editor:

uvx --with pyobservablejs marimo edit notebook.py

Create and render a notebook

Paste this into one marimo cell or a JupyterLab cell. anywidget, the widget system connecting Python to browser components, supports these hosts. Notebook Kit evaluates the JavaScript cells in the browser. Its input library loads from the network on first use. See Browser execution for network and code-trust requirements.

import observablejs as obs

control = obs.ojs(
"""
viewof threshold = Inputs.range([0, 1], {
value: 0.5,
step: 0.1,
label: "Threshold"
})
""",
key="threshold",
)

result = obs.js(
"""
const doubled = threshold * 2;
display(html`<strong>Doubled threshold: ${doubled}</strong>`);
""",
key="result",
)

notebook = obs.Notebook(
control,
result,
variables={"threshold": 0.5},
)

view = notebook.view()
view

The slider starts at 0.5, and the readout shows 1. Moving the slider reruns the result cell. key="result" identifies the cell in Python. doubled is the JavaScript value defined by that cell.

Update the browser from Python

Notebook.update_variables accepts one mapping. Every mounted view from this notebook receives the update.

notebook.update_variables({"threshold": 0.8})

Run the update in another cell. The slider moves to 0.8, and the readout shows 1.6.

Read a settled result

NotebookView.state is one consistent, read-only snapshot. Read a result after the current input revision finishes. In marimo, run this in another cell. The view.value reference makes that cell rerun when the view synchronizes. In Jupyter, omit that line and run the reading cell after the view renders.

view.value # marimo subscription
state = view.state

if state.errors:
print(state.errors)
elif (
not state.pending
and state.input_revision is not None
and state.settled_revision == state.input_revision
):
result_state = state.result("result")
if result_state.status == "success":
print(result_state.values["doubled"])
else:
print(result_state.errors)

The value is 1.6 after the Python update. Browser interaction changes it again. Read browser results covers observing updates and handling errors.

Continue with How pyobservablejs works, Author notebook cells, Select cells, or Read browser results.