La manera més fàcil d'aprendre a usar Streamlit és provar-ho tu mateix.
Introducció
Streamlit és un framework de codi obert per crear apps que és molt fàcil per començar.
Conceptes bàsics
Crea un projecte streamlit-basic
amb uv:
uv init streamlit-basic
cd streamlit-basic
uv add streamlit
Treballar amb Streamlit és senzill.
Primer, afegeixes algunes instruccions de Streamlit a un script Python normal.
Modifica el fitxer main.py
:
import streamlit as st
st.write("Hello, world!")
Després l’executes amb streamlit run
:
uv run streamlit run main.py
Tan bon punt executis l’script com es mostra a dalt, s’aixecarà un servidor local de Streamlit i la teva app s’obrirà en una pestanya nova del navegador per defecte. L’app és el teu llenç, on dibuixaràs gràfics, text, ginys, taules i més.
El que es mostra a l’app depèn de tu. Per exemple, st.text
escriu text en brut a la teva app.
Flux de desenvolupament
Cada vegada que vulguis actualitzar la teva app, desa el fitxer font. Quan ho facis, Streamlit detecta si hi ha canvis i et pregunta si vols tornar a executar l’app. Tria “Always rerun” a la part superior dreta per actualitzar automàticament la teva app cada vegada que canviïs el codi font.
Això et permet treballar en un bucle interactiu ràpid: escrius una mica de codi, el deses, ho proves en viu, tornes a escriure codi, el deses, ho proves, i així successivament fins que estiguis satisfet amb els resultats. Aquest bucle ajustat entre codificar i veure resultats en viu és una de les maneres en què Streamlit et fa la vida més fàcil.
Flux de dades
L’arquitectura de Streamlit et permet escriure apps de la mateixa manera que escrius scripts Python normals. Per aconseguir-ho, les apps de Streamlit tenen un flux de dades únic: cada vegada que alguna cosa s’ha d’actualitzar a la pantalla, Streamlit torna a executar tot l’script de Python de dalt a baix.
Això pot passar en dues situacions:
-
Sempre que modifiques el codi font de l’app.
-
Sempre que un usuari interactua amb els ginys de l’app. Per exemple, en arrossegar un control lliscant, entrar text en una caixa d’entrada o fer clic en un botó.
Sempre que un callback es passa a un giny a través del paràmetre on_change
(o on_click
), el callback s’executa abans de la resta de l’script. Per a detalls sobre la API de callbacks, consulta la Session State API Reference Guide.
I per fer que tot això sigui ràpid i fluid, Streamlit fa molta feina per tu en segon pla. Una peça clau és el decorador @st.cache_data
, que permet evitar certs càlculs costosos quan l’app es torna a executar. Més endavant en aquesta pàgina parlarem de la memòria cau.
Crea una app
Faràs servir les funcionalitats bàsiques de Streamlit per crear una app interactiva explorant un conjunt de dades públic d’Uber de recollides i deixades a la ciutat de Nova York.
Quan acabis, sabràs com obtenir i posar en memòria cau dades, dibuixar gràfics, representar informació en un mapa i utilitzar ginys interactius, com un control lliscant, per filtrar resultats.
Afegeix una dependència amb Polars:
uv add polars
Obté dades
Ara que tens una app, el següent que necessites és obtenir el conjunt de dades d’Uber de recollides i deixades a Nova York.
Comencem escrivint una funció per carregar les dades. Afegeix aquest codi a l’script:
import polars as pl
DATE_COLUMN = 'date/time'
DATA_URL = ('https://s3-us-west-2.amazonaws.com/'
'streamlit-demo-data/uber-raw-data-sep14.csv.gz')
# ...
Veureu que load_data
és una funció normal que descarrega dades, les posa en un dataframe de Pandas i converteix la columna de dates de text a datetime. La funció accepta un únic paràmetre (n_rows
), que especifica el nombre de files que vols carregar al dataframe.
Ara provem la funció i revisem la sortida. A sota de la funció, afegeix aquestes línies:
# Create a text element and let the reader know the data is loading.
data_load_state = st.text('Loading data...')
# Load 10,000 rows of data into the dataframe.
data = load_data(10000)
# Notify the reader that the data was successfully loaded.
data_load_state.text('Loading data...done!')
Veureu alguns botons a la cantonada superior dreta de la teva app preguntant si vols tornar a executar-la. Tria Always rerun, i veuràs els canvis automàticament cada vegada que desis.
D’acord, això no impressiona gaire…
Resulta que descarregar dades i carregar 10.000 files en un dataframe triga força. Convertir la columna de data a datetime tampoc és ràpid. No vols tornar a carregar les dades cada vegada que s’actualitza l’app – per sort Streamlit permet posar-les en memòria cau.
Memòria cau sense esforç
Prova d’afegir @st.cache_data
abans de la declaració de load_data
:
@st.cache_data
def load_data(n_rows):
Després desa l’script i Streamlit tornarà a executar la teva app automàticament. Com que és la primera vegada que executes l’script amb @st.cache_data
, no veuràs cap canvi.
Modifiquem el fitxer una mica més per veure el poder de la memòria cau.
Substitueix la línia data_load_state.text('Loading data...done!')
per aquesta:
data_load_state.text("Done! (using st.cache_data)")
Ara desa. Veus com la línia que has afegit ha aparegut immediatament? Si ho penses, això és força sorprenent. Passa alguna cosa “màgica” en segon pla, i només cal una línia de codi per activar-ho.
Com funciona?
Prenem uns minuts per comentar com funciona realment @st.cache_data
.
Quan marques una funció amb l’anotació de memòria cau de Streamlit, li dius a Streamlit que sempre que es cridi la funció comprovi dues coses:
- Els paràmetres d’entrada que has fet servir en la crida.
- El codi dins de la funció.
Si és la primera vegada que Streamlit veu aquests dos elements, amb aquests valors exactes i en aquesta combinació exacta, executa la funció i n’emmagatzema el resultat a una memòria cau local. La propera vegada que es cridi la funció, si aquests dos valors no han canviat, Streamlit sap que pot saltar-se l’execució de la funció. En lloc d’això, llegeix la sortida des de la memòria cau local i la retorna — com per art de màgia.
“Però, un moment,” pots pensar, “això sona massa bé. Quines són les limitacions?”
N’hi ha algunes:
-
Streamlit només comprovarà canvis dins del directori de treball actual. Si actualitzes una llibreria de Python, la memòria cau de Streamlit només se n’adonarà si aquesta llibreria està instal·lada dins del teu directori de treball.
-
Si la funció no és determinista (és a dir, la sortida depèn d’aleatorietat) o si obté dades d’una font externa que varia en el temps (per exemple, un servei de cotitzacions en temps real), el valor en memòria cau no en serà conscient.
-
Finalment, evita mutar la sortida d’una funció emmagatzemada amb
st.cache_data
, ja que els valors a la memòria cau es guarden per referència.
Tot i que cal tenir en compte aquestes limitacions, sovint no són un problema. Quan no ho són, aquesta memòria cau és realment transformadora.
Now that you know how caching with Streamlit works, let’s get back to the Uber pickup data.
Ara que saps com funciona la memòria cau amb Streamlit, tornem a les dades de recollides d’Uber.
Inspecciona les dades en brut
Sempre és bona idea donar un cop d’ull a les dades en brut amb què treballes abans de començar. Afegim una subcapçalera i una taula de les dades en brut a l’app:
st.subheader("Raw data")
st.write(data)
A la guia de Conceptes bàsics pots aprendre que st.write
renderitza gairebé qualsevol cosa que li passis. En aquest cas, passes un dataframe i es mostra com una taula interactiva.
st.write
intenta fer el més adient segons el tipus de dades d’entrada. Si no fa el que esperes, pots utilitzar una instrucció especialitzada com st.dataframe
. Per a la llista completa, mira la referència de l’API.
Dibuixa un histograma
Després de donar un cop d’ull al conjunt de dades i veure què hi ha, fem un pas més i dibuixem un histograma per veure quines són les hores amb més recollides d’Uber a Nova York.
Per començar, afegeix una subcapçalera just sota la secció de dades en brut:
st.subheader('Number of pickups by hour')
Fes servir NumPy per generar un histograma que agrup i les hores de recollida:
hist_values = np.histogram(data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0]
Ara utilitza el mètode st.bar_chart()
de Streamlit per dibuixar aquest histograma.
st.bar_chart(hist_values)
Desa l’script.
Aquest histograma hauria d’aparèixer a l’app de seguida. Després d’una revisió ràpida, sembla que l’hora més concorreguda és les 17:00 (5 de la tarda).
Per dibuixar aquest diagrama hem usat el mètode nadiu bar_chart()
de Streamlit, però és important saber que Streamlit també admet llibreries de gràfics més complexes com Altair, Bokeh, Plotly, Matplotlib i més.
Per a la llista completa, consulta les llibreries de gràfics admeses.
Representa dades en un mapa
Amb l’histograma hem determinat quines són les hores més concorregudes per a recollides d’Uber, però i si volem saber on es concentren les recollides per la ciutat? Podries usar un diagrama de barres, però no seria fàcil d’interpretar si no coneixes molt bé les coordenades. Per mostrar la concentració de recollides, utilitzem la funció st.map()
de Streamlit per superposar les dades a un mapa de Nova York.
Afegeix una subcapçalera per a la secció:
st.subheader('Map of all pickups')
Utilitza la funció st.map()
per representar les dades:
st.map(data)
Desa l’script.
El mapa és totalment interactiu. Prova de moure’l o fer zoom.
Després de dibuixar l’histograma, has determinat que l’hora amb més recollides d’Uber era les 17:00. Tornem a dibuixar el mapa per mostrar la concentració de recollides a les 17:00.
Localitza aquest fragment de codi:
st.subheader('Map of all pickups')
st.map(data)
Substitueix-lo per:
hour_to_filter = 17
filtered_data = data[data[DATE_COLUMN].dt.hour == hour_to_filter]
st.subheader(f'Map of all pickups at {hour_to_filter}:00')
st.map(filtered_data)
Hauries de veure les dades actualitzar-se a l’instant.
Per dibuixar aquest mapa hem utilitzat la funció st.map
integrada a Streamlit, però si vols visualitzar dades cartogràfiques més complexes, dona un cop d’ull a st.pydeck_chart.
Filtra dades amb un control lliscant
A l’última secció, quan vas dibuixar el mapa, l’hora per filtrar resultats estava codificada al codi, però i si volem deixar que el lector filtri dinàmicament en temps real? Amb els ginys de Streamlit pots fer-ho.
Afegim un control lliscant a l’app amb el mètode st.slider()
.
Localitza hour_to_filter
i substitueix-lo per aquest codi:
hour_to_filter = st.slider("hour", 0, 23, 17) # min: 0h, max: 23h, default: 17h
Fes servir el slider i observa com s’actualitza el mapa en temps real.
Usa un botó per alternar dades
Els controls lliscants són només una manera de canviar dinàmicament la composició de la teva app. Fem servir la funció st.checkbox
per afegir una casella de selecció a l’app. La farem servir per mostrar/amagar la taula de dades en brut a la part superior de l’app.
Localitza aquestes línies:
st.subheader('Raw data')
st.write(data)
Substitueix-les per aquest codi:
if st.checkbox('Show raw data'):
st.subheader('Raw data')
st.write(data)
Segur que tens les teves pròpies idees. Quan acabis aquest tutorial, consulta tots els ginys que Streamlit ofereix a la Referència de l’API.
Usa un botó per alternar dades
Els controls lliscants són només una manera de canviar dinàmicament la composició de la teva app. Fem servir la funció st.checkbox
per afegir una casella de selecció a l’app. La farem servir per mostrar/amagar la taula de dades en brut a la part superior de l’app.
Localitza aquestes línies:
st.subheader('Raw data')
st.write(data)
Substitueix-les per aquest codi:
if st.checkbox('Show raw data'):
st.subheader('Raw data')
st.write(data)
Comparteix la teva app
Després d’haver construït una app amb Streamlit, és hora de compartir-la! Per ensenyar-la al món pots utilitzar la Streamlit Community Cloud per desplegar, gestionar i compartir la teva app de franc.
Funciona en 3 passos senzills:
- Posa la teva app en un repositori públic de GitHub
- Inicia sessió a share.streamlit.io
- Fes clic a “Deploy an app” i enganxa l’URL del teu GitHub
Això és tot! 🎈 Ara tens una app desplegada públicament que pots compartir amb el món. Clica per saber més sobre com utilitzar Streamlit Community Cloud.
Crea una app multipàgina
A mesura que les apps creixen, és útil organitzar-les en múltiples pàgines. Això fa que l’app sigui més fàcil de gestionar com a desenvolupador i més fàcil de navegar com a usuari. Streamlit proporciona una manera potent de crear apps multipàgina utilitzant st.Page
i st.navigation
.
Només has de crear les teves pàgines i connectar-les amb la navegació així:
- Crea un script d’entrada que defineixi i connecti les pàgines
- Crea fitxers Python separats per al contingut de cada pàgina
- Fes servir
st.Page
per definir les pàgines ist.navigation
per connectar-les
Modifica el contingut del fitxer main.py
per crear una app multipàgina.
import streamlit as st
home = st.Page("home.py", title="Home", icon="🏠")
histogram = st.Page("histogram.py", title="Histogram", icon="📊")
map = st.Page("map.py", title="Map", icon="🗺️")
# Set up navigation
pg = st.navigation([home, histogram, map])
# Run the selected page
pg.run()
Crea un fitxer db.py
per tota la lògica d’accés a les dades.
import streamlit as st
import pandas as pd
import polars as pl
DATE_COLUMN = 'date/time'
DATA_URL = ('https://s3-us-west-2.amazonaws.com/'
'streamlit-demo-data/uber-raw-data-sep14.csv.gz')
@st.cache_data
def load(nrows):
data = pd.read_csv(DATA_URL, nrows=nrows)
lowercase = lambda x: str(x).lower()
data.rename(lowercase, axis='columns', inplace=True)
data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN])
return data
A continuació mou el codi que tenies a main.py
a home.py
, histogram.py
i map.py
.
Ara executa streamlit run main.py
i visualitza la teva nova app multipàgina!
El menú de navegació apareixerà automàticament, permetent als usuaris canviar entre pàgines.
La documentació de Streamlit sobre apps multipàgina t’ensenya com afegir pàgines a la teva app, incloent com definir pàgines, estructurar i executar apps multipàgina i navegar entre pàgines.