6 · Streamlit: the script-rerun model
Streamlit turns a plain Python script into an interactive app — no HTML, no routes, no callbacks. Its one big idea is the rerun model: every time a user touches a widget, Streamlit reruns your WHOLE script top-to-bottom, and the widgets simply return their current values as ordinary Python variables.
Streamlit has NO routes or request handlers — it runs your whole script TOP-TO-BOTTOM and, on EVERY widget interaction, RERUNS the entire script from the top. A widget like `st.slider(...)` both DRAWS the control AND returns its current value as a plain Python variable, so your code reads like a linear script while the page stays interactive. You launch it with `streamlit run app.py`.
Without this:
Without grasping the rerun model, Streamlit code looks like magic that shouldn't work — you'd reach for Flask-style routes and callbacks that Streamlit doesn't have, and misunderstand why a variable 'updates' when you move a slider.
Flask made you think in routes and handlers: a request comes in, a specific function runs, a response goes out. Streamlit throws all of that away. There are no routes, no request object, no callbacks, no HTML to write. You write a plain top-to-bottom Python script, and Streamlit turns it into a live web app. The price of that simplicity is learning one new mental model — and it's unlike anything in Flask.
The rerun model: the whole script runs again on every interaction. This is the idea that makes Streamlit click. When the page first loads, Streamlit runs your script from the first line to the last, and every st.* call paints something onto the page. Then — here's the twist — every time the user touches any widget (drags a slider, picks from a dropdown, clicks a button), Streamlit reruns your entire script from the top again, start to finish. Not one function; the whole file. The page you see is always the result of the most recent full run.
Widgets do two things at once. A widget call like age = st.slider("Age", 0, 100, 25) is deceptively powerful: it both draws the slider on the page and returns the slider's current value into age. On the first run age is the default (25); after the user drags the slider to 40 and the script reruns, that same line now returns 40. So you read widget input by simply assigning the widget call to a variable — no event handlers, no request.form. The core widgets you'll use constantly:
st.title(...)/st.header(...)/st.write(...)— display text, data, almost anything.st.slider(label, min, max, default)— a numeric slider, returns the chosen number.st.selectbox(label, options)— a dropdown, returns the chosen option.st.number_input(label)/st.text_input(label)— typed numeric / text entry.st.button(label)— returnsTrueonly on the run triggered by the click,Falseotherwise.
Why this is so productive. Because the script is linear, you build a UI by just writing Python in order: read a slider, do a calculation, show the result — top to bottom, like a notebook that happens to be interactive. There's no template language and no wiring of inputs to outputs; the rerun loop does it for you.
Run it from the terminal. You don't python app.py a Streamlit app — you launch it with streamlit run app.py, which starts the Streamlit server and opens the app in your browser (typically http://localhost:8501).
The read-along cell shows a tiny but complete Streamlit app; the second cell is the one command that runs it.
A minimal Streamlit app: a linear top-to-bottom script where each `st.slider`/`st.selectbox`/`st.number_input` widget both draws a control and returns its current value — and Streamlit reruns the whole script on every interaction.
Install Streamlit and launch with `streamlit run app.py` (not `python app.py`) — the app opens at `http://localhost:8501` and reruns the script on every interaction.
In a Streamlit app, a user drags a `st.slider` from 12 to 40. What does Streamlit do in response?
- Streamlit has no routes or handlers: you write a linear top-to-bottom Python script, and `streamlit run app.py` turns it into a live web app.
- The rerun model: every widget interaction reruns the ENTIRE script from the top — that rerun is how the page updates, which is why there are no callbacks.
- A widget call both draws the control and returns its current value: `x = st.slider(...)` paints a slider AND assigns its value to `x` on every run.
Streamlit is the fastest way to put a model in front of a human — a few `st.*` widgets read features, and a single `model.predict` line shows a live prediction, no frontend code required.
If you remove it: Without understanding the rerun model, you'd misread Streamlit code as broken or magical and never build the interactive dashboards that make a model explorable to non-coders.