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.