Streamlit és un framework per crear aplicacions web per analitzar dades.
- Introducció
- Script
- Mostrar i estilitzar dades
- Widgets
- Layout
- Memòria cau
- Session State
- Pàgines
- Components personalitzats
- Servei de fitxers estàtics
- Proves d’aplicacions
- Community Cloud
- Activitats
Introducció
Streamlit és un framework per crear aplicacions web per analitzar dades.
- Les aplicacions de Streamlit són scripts de Python que s’executen de dalt a baix.
- Cada vegada que un usuari obre una pestanya del navegador apuntant a la teva aplicació, l’script s’executa i s’inicia una sessió nova.
- A mesura que l’script s’executa, Streamlit dibuixa la seva sortida en directe en un navegador.
- Cada vegada que un usuari interactua amb un widget, el teu script es torna a executar i Streamlit redibuixa la seva sortida al navegador. El valor de sortida d’aquest widget coincideix amb el valor nou durant aquesta reexecució.
- Els scripts utilitzen la memòria cau de Streamlit per evitar recalcular funcions costoses, de manera que les actualitzacions es produeixen molt ràpidament.
- Session State et permet desar informació que persisteix entre reexecucions quan necessites més que un simple widget.
- Les aplicacions de Streamlit poden contenir múltiples pàgines, que es defineixen en fitxers
.py
separats.
Script
Crea un projecte streamlit-basic
amb uv:
uv init streamlit-basic
cd streamlit-basic
uv add streamlit
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 executes 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 widget 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.
Mostrar i estilitzar dades
Hi ha diverses maneres de mostrar dades (taules, arrays, dataframes) en aplicacions de Streamlit.
A continuació, es presenten magic i st.write()
, que es poden utilitzar per escriure qualsevol cosa, des de text fins a taules.
Després d’això, vegem els mètodes dissenyats específicament per visualitzar dades.
Utilitzar magic
També pots escriure a la teva aplicació sense cridar cap mètode de Streamlit.
Streamlit suporta “ordres màgiques” (magic commands), la qual cosa significa que no cal utilitzar st.write()
en absolut!
Crea el fitxer test.py
import streamlit as st
import pandas as pd
df = pd.DataFrame({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40]
})
df
streamlit run test.py
Cada vegada que Streamlit veu una variable o un valor literal en la seva pròpia línia, automàticament l’escriu a la teva aplicació utilitzant st.write()
.
Per a més informació, consulta la documentació sobre ordres màgiques.
Escriure un dataframe
Juntament amb les ordres màgiques, st.write()
és el “ganivet suís” de Streamlit. Pots passar gairebé qualsevol cosa a st.write()
: text, dades, gràfics d’Altair, i molt més. No et preocupis, Streamlit ho entendrà i renderitzarà les coses de la manera correcta.
Hi ha altres funcions específiques per a dades com st.dataframe()
i st.table()
que també pots utilitzar per mostrar dades. Vegem quan utilitzar aquestes funcionalitats i com afegir colors i estils als teus marcs de dades.
Potser et preguntes: “per què no utilitzaria sempre st.write()
?” Hi ha diverses raons:
-
Magic i
st.write()
inspeccionen el tipus de dades que has passat i després decideixen com renderitzar-ho millor a l’aplicació. De vegades vols dibuixar-ho d’una altra manera. Per exemple, en lloc de dibuixar un dataframe com una taula interactiva, potser vols dibuixar-lo com una taula estàtica utilitzantst.table(df)
. -
La segona raó és que altres mètodes retornen un objecte que es pot utilitzar i modificar, sigui afegint-hi dades o reemplaçant-lo.
-
Finalment, si utilitzes un mètode de Streamlit més específic, pots passar arguments addicionals per personalitzar el seu comportament.
PENDENT exemple style
Dibuixar gràfics i mapes
Streamlit suporta diverses biblioteques populars de gràfics de dades com Altair, deck.gl, i més.
En aquesta secció, afegiràs un gràfic de barres, un gràfic de línies i un mapa a la teva aplicació.
Dibuixar un gràfic de línies
Pots afegir fàcilment un gràfic de línies a la teva aplicació amb st.line_chart()
.
import streamlit as st
import numpy as np
import polars as pl
df = pl.DataFrame({
"year": range(2000, 2030),
"sales": np.random.rand(30) * 30000
})
st.line_chart(df, x="year", y="sales")
Dibuixar un mapa
Amb st.map()
pots mostrar punts de dades en un mapa.
Utilitzem Numpy per generar algunes dades de mostra i dibuixar-les en un mapa de Barcelona.
import streamlit as st
import numpy as np
import polars as pl
df = pl.DataFrame({
"lat": np.random.randn(1000) / 50 + 41.38,
"lon": np.random.randn(1000) / 50 + 2.15,
})
st.map(df)
Widgets
Quan hagis aconseguit que les dades o el model estiguin en l’estat que vols explorar, pots afegir widgets com st.slider()
, st.button()
o st.selectbox()
.
És molt senzill: tracta els “widgets” com a variables:
import streamlit as st
x = st.slider('x') # 👈 this is a widget
st.write(x, 'squared is', x * x)
En la primera execució, l’aplicació anterior hauria de mostrar el text “0 al quadrat és 0”. Després, cada vegada que un usuari interactua amb un giny, Streamlit simplement torna a executar el teu script de dalt a baix, assignant l’estat actual del “widget” a la teva variable en el procés.
Per exemple, si l’usuari mou el control lliscant a la posició 10
, Streamlit tornarà a executar el codi anterior i assignarà 10
a x
en conseqüència. Així doncs, ara hauries de veure el text “10 al quadrat és 100”.
Els widgets també es poden accedir per clau, si tries especificar una string per utilitzar-la com a clau única del widget:
import streamlit as st
st.text_input("Your name", key="name")
# You can access the value at any point with:
st.session_state.name
Cada widget amb una clau s’afegeix automàticament a Session State.
Per a més informació sobre Session State, la seva associació amb l’estat dels widgets i les seves limitacions, consulta la Guia de referència de l’API de Session State.
Utilitza caselles de selecció per mostrar/amagar dades
Un cas d’ús per a les caselles de selecció és amagar o mostrar un gràfic o secció específica en una aplicació.
st.checkbox()
accepta un únic argument, que és l’etiqueta del widget.
En aquest codi, la casella de selecció s’utilitza per alternar una instrucció condicional:
import streamlit as st
import numpy as np
import polars as pl
if st.checkbox('Show dataframe'):
df = pl.DataFrame({
"a": np.random.randn(20),
"b": np.random.randn(20)
})
df
Utilitza un selectbox per a opcions
Utilitza st.selectbox
per triar d’una sèrie. Pots escriure les opcions que vulguis, o passar un array o columna de dataframe.
import streamlit as st
import polars as pl
df = pl.DataFrame({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40]
})
option = st.selectbox(
'Which number do you like best?',
df['first column'])
'You selected: ', option
Layout
Streamlit facilita organitzar els teus widgets en una barra lateral esquerra amb st.sidebar
.
Cada element que es passa a st.sidebar
s’enganxa a l’esquerra, cosa que permet als usuaris centrar-se en el contingut de la teva aplicació mentre encara tenen accés als controls de la interfície d’usuari.
Per exemple, si vols afegir un selectbox i un slider a una barra lateral, utilitza st.sidebar.slider
i st.sidebar.selectbox
en lloc de st.slider
i st.selectbox
:
import streamlit as st
# Add a selectbox to the sidebar:
add_selectbox = st.sidebar.selectbox(
'How would you like to be contacted?',
('Email', 'Home phone', 'Mobile phone')
)
# Add a slider to the sidebar:
add_slider = st.sidebar.slider(
'Select a range of values',
0.0, 100.0, (25.0, 75.0)
)
Més enllà de la barra lateral, Streamlit ofereix diverses altres maneres de controlar el layout de la teva aplicació.
st.columns
et permet col·locar widgets un al costat de l’altre, i st.expander
et permet conservar espai amagant contingut gran.
import streamlit as st
left_column, right_column = st.columns(2)
# You can use a column just like st.sidebar:
left_column.button('Press me!')
# Or even better, call Streamlit functions inside a "with" block:
with right_column:
chosen = st.radio(
'Sorting hat',
("Gryffindor", "Ravenclaw", "Hufflepuff", "Slytherin"))
st.write(f"You are in {chosen} house!")
Mostra el progrés
Quan afegeixes càlculs de llarga durada a una aplicació, pots utilitzar st.progress()
per mostrar l’estat en temps real
import streamlit as st
import time
'Starting a long computation...'
# Add a placeholder
latest_iteration = st.empty()
bar = st.progress(0)
for i in range(100):
# Update the progress bar with each iteration.
latest_iteration.text(f'Iteration {i + 1}')
bar.progress(i + 1)
time.sleep(0.1)
'...and now we\'re done!'
Memòria cau
La memòria cau permet que la teva aplicació sigui responsiva fins i tot quan carrega dades des del web, manipula conjunts de dades grans o realitza càlculs costosos.
La idea bàsica darrere de la memòria cau és emmagatzemar els resultats de crides de funcions costoses i retornar el resultat en memòria cau quan es tornen a produir les mateixes entrades. Això evita l’execució repetida d’una funció amb els mateixos valors d’entrada.
Per posar en memòria cau una funció a Streamlit, has d’aplicar-hi un decorador de memòria cau.
Tens dues opcions:
-
st.cache_data
és la manera recomanada de posar en memòria cau càlculs que retornen dades. Utilitzast.cache_data
quan utilitzis una funció que retorna un objecte de dades serialitzable (p. ex.str
,int
,float
,DataFrame
,dict
,list
). Crea una nova còpia de les dades en cada crida de funció, fent-la segura contra mutations and reace conditions. El comportament dest.cache_data
és el que vols en la majoria dels casos: així que si tens dubtes, comença ambst.cache_data
i mira si funciona! -
st.cache_resource
és la manera recomanada de posar en memòria cau recursos globals com models de ML o connexions de bases de dades. Utilitzast.cache_resource
quan la teva funció retorni objectes no serialitzables que no vols carregar múltiples vegades. Retorna el mateix objecte en memòria cau, que es comparteix entre totes les reexecucions i sessions sense còpia ni duplicació. Si mutes un objecte que està en memòria cau utilitzantst.cache_resource
, aquesta mutació existirà en totes les reexecucions i sessions.
@st.cache_data
def long_running_function(param1, param2):
return …
En l’exemple anterior, long_running_function
està decorada amb @st.cache_data
.
Com a resultat, Streamlit anota el següent:
- El nom de la funció (
"long_running_function"
). - El valor de les entrades (
param1
,param2
). - El codi dins de la funció.
Abans d’executar el codi dins de long_running_function
, Streamlit comprova la seva memòria cau per trobar un resultat guardat prèviament. Si troba un resultat en memòria cau per a la funció i els valors d’entrada donats, retornarà aquest resultat en memòria cau i no tornarà a executar el codi de la funció. En cas contrari, Streamlit executa la funció, guarda el resultat a la seva memòria cau i continua amb l’execució de l’script. Durant el desenvolupament, la memòria cau s’actualitza automàticament a mesura que canvia el codi de la funció, assegurant que els últims canvis es reflecteixin a la memòria cau.
Per a més informació sobre els decoradors de memòria cau de Streamlit, els seus paràmetres de configuració i les seves limitacions, consulta Caching.
Session State
Session State proporciona una interfície semblant a un diccionari on pots guardar informació que es conserva entre reexecucions d’scripts.
Utilitza st.session_state
amb notació de clau o atribut per emmagatzemar i recuperar valors. Per exemple, st.session_state["my_key"]
o st.session_state.my_key
.
Recorda que els widgets gestionen el seu propi estat per si mateixos, així que no sempre necessitaràs utilitzar Session State!
Què és una sessió?
Una sessió és una única instància de visualització d’una aplicació. Si visualitzes una aplicació des de dues pestanyes diferents del teu navegador, cada pestanya tindrà la seva pròpia sessió. Així doncs, cada visualitzador d’una aplicació tindrà un Session State vinculat a la seva visualització específica. Streamlit manté aquesta sessió a mesura que l’usuari interactua amb l’aplicació. Si l’usuari refresca la pàgina del seu navegador o recarrega l’URL de l’aplicació, el seu Session State es reinicia i comença de nou amb una sessió nova.
Exemples d’ús de Session State
Aquí tens una aplicació senzilla que compta el nombre de vegades que s’ha executat la pàgina.
Cada vegada que fas clic al botó, l’script es tornarà a executar.
import streamlit as st
if "counter" not in st.session_state:
st.session_state.counter = 0
st.session_state.counter += 1
st.header(f"This page has run {st.session_state.counter} times.")
st.button("Run it again")
-
Primera execució: La primera vegada que l’aplicació s’executa per a cada usuari, Session State és buit. Per tant, es crea un parell clau-valor (
"counter":0
). A mesura que l’script continua, el comptador s’incrementa immediatament ("counter":1
) i es mostra el resultat: “Aquesta pàgina s’ha executat 1 vegades.” Quan la pàgina s’ha renderitzat completament, l’script ha acabat i el servidor de Streamlit espera que l’usuari faci alguna cosa. Quan aquest usuari fa clic al botó, comença una reexecució. -
Segona execució: Com que “counter” ja és una clau a Session State, no es reinicialitza. A mesura que l’script continua, el comptador s’incrementa (
"counter":2
) i es mostra el resultat: “Aquesta pàgina s’ha executat 2 vegades.”
Hi ha alguns escenaris comuns on Session State és útil. Com s’ha demostrat més amunt, Session State s’utilitza quan tens un procés progressiu que vols construir d’una reexecució a la següent. Session State també es pot utilitzar per evitar recàlculs, de manera similar a la memòria cau. Tot i així, les diferències són importants:
-
La memòria cau associa valors emmagatzemats a funcions i entrades específiques. Els valors en memòria cau són accessibles a tots els usuaris en totes les sessions.
-
Session State associa valors emmagatzemats a claus (strings). Els valors en Session State només estan disponibles en la sessió única on es van guardar.
Si tens generació de nombres aleatoris a la teva aplicació, probablement utilitzaries Session State. Aquí tens un exemple on les dades es generen aleatòriament al principi de cada sessió. En guardar aquesta informació aleatòria a Session State, cada usuari obté dades aleatòries diferents quan obre l’aplicació, però no canviaran constantment mentre hi interactuen.
Si obres l’aplicació en una nova pestanya per començar una sessió nova, veuràs dades diferents!
import streamlit as st
import polars as pl
import numpy as np
if "df" not in st.session_state:
st.session_state.df = pl.DataFrame({
"x": np.random.randn(20),
"y": np.random.randn(20)
})
st.header("Choose a datapoint color")
color = st.color_picker("Color", "#FF0000")
st.divider()
st.scatter_chart(st.session_state.df, x="x", y="y", color=color)
Si estàs obtenint les mateixes dades per a tots els usuaris, probablement posaries en memòria cau una funció que recupera aquestes dades. D’altra banda, si obtens dades específiques d’un usuari, com ara consultar la seva informació personal, potser voldries guardar-les a Session State. D’aquesta manera, les dades consultades només estan disponibles en aquella sessió única.
Com s’ha esmentat anteriorment, Session State també està relacionat amb els widgets. Els widgets són màgics i gestionen el seu estat silenciosament pel seu compte. Com a característica avançada, però, pots manipular el valor dels widgets dins del teu codi assignant-los claus. Qualsevol clau assignada a un widget es converteix en una clau a Session State vinculada al valor del widget. Això es pot utilitzar per manipular el widget. Després d’acabar d’entendre els conceptes bàsics de Streamlit, consulta la guia sobre Widget behavior per aprofundir en els detalls si t’interessa.
Connexions
Com s’ha indicat més amunt, pots utilitzar @st.cache_resource
per posar connexions en memòria cau. Aquesta és la solució més general que et permet utilitzar gairebé qualsevol connexió de qualsevol biblioteca de Python.
No obstant això, Streamlit també ofereix una manera convenient de gestionar algunes de les connexions més populars, com SQL!
st.connection
s’encarrega de la memòria cau per tu, així que pots gaudir de menys línies de codi.
Obtenir dades de la teva base de dades pot ser tan fàcil com:
import streamlit as st
conn = st.connection("my_database")
df = conn.query("select * from my_table")
st.dataframe(df)
Per descomptat, potser et preguntes on van el teu nom d’usuari i contrasenya. Streamlit té un mecanisme convenient per a la gestió de secrets.
Per ara, vegem com st.connection
funciona molt bé amb els secrets. Al directori del teu projecte local, pots desar un fitxer .streamlit/secrets.toml
. Deses els teus secrets al fitxer toml i st.connection
simplement els utilitza!
Per exemple, si tens un fitxer d’aplicació main.py
, el directori del teu projecte podria tenir aquest aspecte:
project/
├── .streamlit/
│ └── secrets.toml # Make sure to gitignore this!
└── main.py
Per a l’exemple SQL anterior, el teu fitxer secrets.toml
podria tenir aquest aspecte:
[connections.postgresql]
dialect = "postgresql"
host = "localhost"
port = "5432"
database = "xxx"
username = "xxx"
password = "xxx"
PENDENT: moure a streamlit/database
:
Com que no vols fer commit del teu fitxer secrets.toml
al repositori, hauràs d’aprendre com el teu servidor gestiona els secrets quan estiguis preparat per publicar la teva aplicació.
Cada plataforma de servidor pot tenir una manera diferent perquè hi passis els teus secrets. Si utilitzes Streamlit Community Cloud, per exemple, cada aplicació desplegada té un menú de configuració on pots carregar els teus secrets.
Pàgines
A mesura que les aplicacions creixen, resulta útil organitzar-les en múltiples pàgines. Això fa que l’aplicació 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 aplicacions multipàgina utilitzant st.Page
i st.navigation
.
Simplement crea les teves pàgines i connecta-les amb navegació de la manera següent:
- Crea un script de punt d’entrada que defineixi i connecti les teves pàgines
- Crea fitxers Python separats per al contingut de cada pàgina
- Utilitza
st.Page
per definir les teves pàgines ist.navigation
per connectar-les
Aquí tens un exemple d’una aplicació de tres pàgines:
import streamlit as st
# Define the pages
main_page = st.Page("main_page.py", title="Main Page", icon="🎈")
page_2 = st.Page("page_2.py", title="Page 2", icon="❄️")
page_3 = st.Page("page_3.py", title="Page 3", icon="🎉")
# Set up navigation
pg = st.navigation([main_page, page_2, page_3])
# Run the selected page
pg.run()
import streamlit as st
# Main page content
st.markdown("# Main page 🎈")
st.sidebar.markdown("# Main page 🎈")
import streamlit as st
st.markdown("# Page 2 ❄️")
st.sidebar.markdown("# Page 2 ❄️")
import streamlit as st
st.markdown("# Page 3 🎉")
st.sidebar.markdown("# Page 3 🎉")
Ara executa streamlit run main.py
i visualitza la teva nova aplicació multipàgina!
El menú de navegació apareixerà automàticament, cosa que permet als usuaris canviar entre pàgines. Aplicacions multipàgina t’ensenya com afegir pàgines a la teva aplicació, incloent com definir pàgines, estructurar i executar aplicacions multipàgina, i navegar entre pàgines.
Components personalitzats
Si no pots trobar el component adequat dins de la biblioteca de Streamlit, prova els components personalitzats per estendre la funcionalitat integrada de Streamlit.
Explora i navega pels components populars creats per la comunitat a la galeria de components.
Si et dediques al desenvolupament frontend, pots construir el teu propi component personalitzat amb l’API de components de Streamlit.
Servei de fitxers estàtics
Com vas aprendre als fonaments de Streamlit, Streamlit executa un servidor al qual es connecten els clients. Això significa que els espectadors de la teva aplicació no tenen accés directe als fitxers que són locals a la teva aplicació. La major part del temps, això no importa perquè les ordres de Streamlit ho gestionen per tu.
Quan utilitzes st.image(<ruta-a-imatge>)
, el teu servidor de Streamlit accedirà al fitxer i gestionarà l’allotjament necessari perquè els espectadors de la teva aplicació puguin veure-la. No obstant això, si vols una URL directa a una imatge o fitxer, hauràs d’allotjar-lo. Això requereix establir la configuració correcta i col·locar els teus fitxers allotjats en un directori anomenat static
.
Per exemple, el teu projecte podria tenir aquest aspecte:
project/
├── static/
│ └── dog.png
└── main_app.py
Per saber-ne més, llegeix la guia sobre servei de fitxers estàtics.
Proves d’aplicacions
Una bona higiene de desenvolupament inclou provar el teu codi. Les proves automatitzades et permeten escriure codi de més qualitat, més ràpidament! Streamlit té un framework de proves integrat que et permet construir proves fàcilment. Utilitza el teu framework de proves favorit per executar les teves proves.
Quan proves una aplicació de Streamlit, simules l’execució de l’aplicació, declares l’entrada de l’usuari i inspecciones els resultats. Pots utilitzar fluxos de treball de GitHub per automatitzar les teves proves i rebre alertes instantànies sobre canvis que trenquen el codi. Aprèn més a la guia sobre proves d’aplicacions.
Community Cloud
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.
Activitats
Mira aquest lloc web i fes alguns dels exemples: Learn Streamlit