technik
Streamlit: der schnellste Weg von einem Python-Skript zur fertigen Daten-App
Streamlit verwandelt einfache Python-Skripte in interaktive Web-Apps, ohne eine Zeile HTML, CSS oder JavaScript schreiben zu müssen. Hier der vollständige Überblick: wie die Rerun-Architektur funktioniert, alle Widget-Typen, Caching und Session-State, Multi-Page-Apps, Custom Components, Theming, Deployment, Sicherheit und wie es sich gegen Dash, Gradio und Panel behauptet.
KI-Entwurf · geprüft und bearbeitetDieser Text wurde mit KI als Erstentwurf erstellt und anschließend von der Autorin bzw. dem Autor geprüft und bearbeitet, die bzw. der die redaktionelle Verantwortung dafür trägt.Streamlit: der schnellste Weg von einem Python-Skript zur fertigen Daten-App
Jeder Data Scientist, ML-Engineer und Analyst stößt irgendwann auf dieselbe Hürde: Sie haben ein Python-Skript, das etwas Nützliches liefert — eine Modellvorhersage, einen bereinigten Datensatz, eine Grafik — aber niemand sonst kann es nutzen. Das Skript liegt auf Ihrem Laptop. Ihr Vorgesetzter hat kein Python installiert. Ihr Kunde will eine URL, die er im Browser öffnen kann. Die herkömmlichen Lösungen sind mühsam: React lernen, eine Flask-API aufsetzen, ein Vue-Frontend deployen, sich mit CSS herumschlagen. Streamlit existiert, um all das überflüssig zu machen.
Streamlit ist ein Open-Source-Python-Framework, mit dem Sie Daten-Skripte in wenigen Minuten in teilbare Web-Apps verwandeln — ganz ohne Frontend-Erfahrung. Schreiben Sie Python, erhalten Sie eine Web-App. Das ist der gesamte Mehrwert.
Dieser Artikel ist eine umfassende, meinungsbetonte Tour durch alles, was Streamlit zu bieten hat: das Ausführungsmodell, das es einzigartig macht, alle wichtigen Widgets und Layout-Primitives, Caching und State-Management, Multi-Page-Apps, Custom Components, Theming, Sicherheit, Deployment und ein realistischer Vergleich mit den Alternativen. Wenn Sie Streamlit für ein Projekt evaluieren, sollte dies der letzte Leitfaden sein, den Sie brauchen.
Was Streamlit wirklich ist (und was es nicht ist)
Streamlit ist ein skriptbasiertes reaktives Framework für den Bau von Daten-Web-Apps. Sie schreiben ein Python-Skript von oben nach unten, und Streamlit verwandelt jede Zeile in ein Browser-Element. Es gibt keine HTML-Vorlage, keine CSS-Datei, kein JavaScript-Bundle, das Sie verwalten müssen. Das Skript ist die App.
Streamlit ist:
- Open Source. Apache-2.0-Lizenz. Für immer kostenlos für jeden Anwendungsfall.
- Reines Python. Keine JavaScript-, HTML- oder CSS-Kenntnisse erforderlich.
- Hot-Reloading. Speichern Sie Ihr Skript, und der Browser aktualisiert sich in Echtzeit.
- Teilbar. Stellen Sie es mit einem Klick auf Streamlit Community Cloud bereit oder hosten Sie es überall mit Docker.
Streamlit ist kein Allzweck-Web-Framework. Sie würden damit kein vollwertiges SaaS-Produkt bauen. Es ist speziell für datenzentrierte interaktive Apps konzipiert — Dashboards, Modell-Demos, Datenexplorer, Reporting-Tools, interne Hilfsprogramme. Wenn Ihre Hauptausgabe eine JavaScript-lastige UI ist, brauchen Sie etwas anderes.
Erste Schritte: Installation und Ihre erste App
Installation ist ein Befehl:
pip install streamlitErstellen Sie eine Datei namens app.py:
import streamlit as st
st.title("My first Streamlit app")
name = st.text_input("What is your name?")
if name:
st.write(f"Hello, {name}! 👋")
number = st.slider("Pick a number", 0, 100, 50)
st.write(f"You chose: {number}")Führen Sie sie aus:
streamlit run app.pyIhr Browser öffnet sich bei http://localhost:8501 mit einer live-interaktiven App. Bewegen Sie einen Schieberegler, und die Seite rendert sofort neu. Jedes Element auf dem Bildschirm wurde von diesem winzigen Skript erzeugt. Das ist der gesamte Entwicklungszyklus — bearbeiten, speichern, sehen.
Das Ausführungsmodell: warum Streamlit anders funktioniert
Das ist das wichtigste Konzept in Streamlit und der Grund, warum es sich von jedem anderen Web-Framework unterscheidet, das Sie bisher genutzt haben. Wenn ein Nutzer mit einem Widget interagiert — Text eingibt, einen Button klickt, einen Schieberegler bewegt — führt Streamlit nicht eine Handler-Funktion auf. Es führt das gesamte Skript von oben bis unten neu aus.
Jede Interaktion löst eine vollständige Neuausführung des Skripts aus. Ihr Skript ist die App. Es gibt keinen Callback, keine Event-Loop, kein virtuelles DOM. Das Skript läuft von der ersten bis zur letzten Zeile, und was es ausgibt, sieht der Nutzer.
Dieses Design hat drei Konsequenzen, die relevant sind:
- Deterministisches Rendering. Die Oberfläche ist stets ein getreues Abbild des aktuellen Skriptzustands. Es gibt kein Problem mit „veralteten Ansichten“ — was Sie sehen, ist das, was das Skript gerade erzeugt hat.
- Widget-Werte bleiben über Neuausführungen hinweg erhalten. Streamlit verfolgt automatisch, welches Widget welchen Wert erzeugt hat, sodass ein Schieberegler seine Position zwischen Neuausführungen behält, ohne dass Sie Code für das Zustandsmanagement schreiben müssen.
- Performance erfordert explizites Caching. Da das gesamte Skript bei jeder Interaktion neu ausgeführt wird, werden teure Operationen (Datenbankabfragen, Modell-Inferenz, das Einlesen großer Dateien) bei jeder Neuausführung wiederholt, sofern Sie sie nicht explizit cachen. Das ist der einzige Bereich, in dem Streamlit bewusste Überlegung verlangt.
Jeder Widget-Typ: Eingaben, Ausgaben und interaktive Elemente
Streamlit liefert eine umfangreiche Bibliothek mit integrierten Widgets aus. Jedes Widget ist ein Funktionsaufruf — keine Konfigurationsobjekte, kein Komponenten-Lebenszyklus. Hier die vollständige Übersicht, nach Zweck gruppiert:
Text- und Zahleneingaben
st.text_input(label)— einzeiliges Textfeld. Gibt einen String zurück.st.text_area(label)— mehrzeiliges Textfeld. Nützlich für längere Eingaben.st.number_input(label, min_val, max_val)— numerische Eingabe mit Schrittpfeilen und Minimal-/Maximalwerten.st.password_input(label)— Textfeld mit Maskierung der Zeichen (ersetzt den alten Parametertype="password").
Schieberegler, Auswahlelemente und Datumsauswahl
st.slider(label, min, max, value)— Schieberegler für einen Wert oderst.slider(label, min, max, value=(low, high))für einen Bereich.st.select_slider(label, options)— Schieberegler mit diskreten Optionen statt numerischer Werte.st.selectbox(label, options)— Dropdown-Auswahl. Gibt den ausgewählten Wert zurück.st.multiselect(label, options)— Mehrfachauswahl-Dropdown. Gibt eine Liste zurück.st.radio(label, options)— Optionsfeldgruppe.st.checkbox(label)— einzelne Checkbox. GibtTrueoderFalsezurück.st.date_input(label)— Datumsauswahl.st.time_input(label)— Zeitauswahl.
Datei-Upload und Medien
st.file_uploader(label, type)— Datei-Upload per Drag-and-drop. AkzeptierttypeFilter (z. B.["csv", "xlsx"]).st.camera_input(label)— Aufnahme eines Bilds von der Webcam des Nutzers.st.audio(data)— Einbettung eines Audio-Players.st.video(data)— Einbettung eines Video-Players.st.image(image)— Anzeige eines Bilds aus einem Dateipfad, einer URL, einem NumPy-Array oder einem PIL-Image.
Schaltflächen, Formulare und Ausführungssteuerung
st.button(label)— Klick-Schaltfläche. GibtTruenur beim erneuten Durchlauf unmittelbar nach dem Klick zurück (Truefür einen Durchlauf).st.form_submit_button(label)— Absende-Schaltfläche innerhalb eines Formulars (Widgets in einem Formular werden nur gemeinsam übermittelt).st.form(key)— Gruppiert Widgets, sodass das Skript erst nach dem Absenden neu ausgeführt wird – nicht bei jedem Tastenanschlag.st.download_button(label, data, file_name)— Stellt einen Download-Link für Daten bereit (String, Bytes oder Datei).st.link_button(label, url)— Rendert einen externen Hyperlink als Schaltfläche.st.toggle(label)— Ein-/Aus-Schalter. Wie eine Checkbox, aber optisch als Kippschalter.st.popover(label)— Eine Schaltfläche, die ein kleines Popover-Panel mit Inhalt öffnet.
Das st.form() ist besonders wichtig für die Nutzererfahrung: Ohne Formular löst jeder Tastenanschlag im Textfeld einen vollständigen Skript-Durchlauf aus. Die Gruppierung von Eingaben in einem Formular verschiebt die Neuausführung auf den Klick der Absende-Schaltfläche – das reduziert die Serverlast deutlich und verbessert die Reaktionsgeschwindigkeit.
Ausgabe und Datenanzeige
st.dataframe(df)— interaktive Tabelle mit Sortierung, Filterung, Suche und Spaltengrößenanpassung. Unterstützt Pandas, Polars und Arrow.st.data_editor(df)— bearbeitbare Version vonst.dataframe. Nutzer können Zeilen hinzufügen/löschen/umordnen, Zellen bearbeiten und Spalten einfügen. Gibt den bearbeiteten Dataframe zurück.st.table(df)— statische, nicht-interaktive Tabelle (in der Praxis selten genutzt).st.metric(label, value, delta)— große Zahl mit optionaler Delta-Anzeige. Für KPI-Dashboards konzipiert.st.json(obj)— schön formatierter, zusammenklappbarer JSON-Baum.st.code(code, language)— syntaxhervorgehobener Codeblock mit Kopierbutton.st.latex(expr)— rendert LaTeX-Mathematikausdrücke.st.progress(value)— Fortschrittsbalken.st.status(label, state)— ausklappbarer Status-Container mit"running"-,"complete"- oder"error"-Zustand.st.toast(message)— flüchtige Toast-Benachrichtigung (ohne Unterbrechung des Seitenlayouts).st.balloons()— Konfettiballons. Ja, wirklich.st.snow()— Schneeflocken. Für die Feiertage.
Native Diagrammerstellung
Streamlit bietet integrierte Wrapper für die gängigsten Python-Diagrammbibliotheken:
st.line_chart(df)— Liniendiagramm, betrieben von Apache ECharts.st.area_chart(df)— gestapeltes Flächendiagramm.st.bar_chart(df)— Balkendiagramm.st.scatter_chart(df)— Streudiagramm.st.map(df)— geografische Karte (Breiten-/Längengradspalten werden automatisch erkannt). Nutzt Deck.gl.- Drittanbieter-Bibliotheken funktionieren nahtlos:
st.pyplot(fig)für Matplotlib,st.plotly_chart(fig)für Plotly,st.bokeh_chart(fig)für Bokeh,st.altair_chart(chart)für Altair.
Layout: Spalten, Seitenleiste, Tabs und Container
Streamlit bietet mehrere Layout-Grundbausteine, um Inhalte über das Standard-Einspaltenlayout hinaus anzuordnen:
st.sidebar— ein dauerhaftes Seitenpanel links. Jedes hier platzierte Widget ist vom Hauptinhaltsbereich getrennt. Hier platzieren die meisten Apps Filter und Konfigurationen.col1, col2, col3 = st.columns(3)— teilt die Seite in Spalten (beliebige Anzahl). Breiten lassen sich mit demratioParameter anpassen (z. B.st.columns([2, 1, 1])für eine Aufteilung 50–25–25).st.tabs(["A", "B", "C"])— Layout mit Tabs. Jeder Tab ist ein Context Manager: Inhalte, die innerhalb eines Tabs geschrieben werden, erscheinen nur dort.st.expander("Details")— ausklappbarer Abschnitt. Standardmäßig ausgeblendet, wird bei Klick expandiert.st.container()— unsichtbarer Gruppierungs-Container. Nützlich für bedingtes Rendern oder das Anwenden von Stilen auf eine Gruppe von Elementen.st.empty()— ein Platzhalter, der überschrieben werden kann. Aufruf vonplaceholder.empty()löscht ihn, oderplaceholder.write("new")ersetzt seinen Inhalt.st.columns(spec, vertical_alignment)— unterstütztvertical_alignment="top","center"oder"bottom", um Spalten vertikal auszurichten.st.container(border=True)— rendert mit sichtbarem Rahmen, nützlich für kartenähnliche Abschnitte.
Zusätzliche Layout-Hilfsmittel umfassen st.divider() (horizontale Linie), st.caption(text) (kleiner, abgedunkelter Text), st.markdown(text) (volle Markdown-Unterstützung inklusive Überschriften, Fett, Kursiv, Links und sogar HTML mit unsafe_allow_html=True)).
Styling und benutzerdefiniertes CSS
Streamlit hat ein sauberes Standarddesign, das sich nicht über API-Parameter anpassen lässt. Um es zu überschreiben, injizieren Sie benutzerdefiniertes CSS:
st.markdown(
"""
<style>
.stApp { background-color: #0e1117; }
h1 { color: #00d4aa; }
</style>
""",
unsafe_allow_html=True,
)Für tiefgreifendere Theming-Anpassungen unterstützt Streamlit eine .streamlit/config.toml -Datei, die das Theme global steuert:
[theme]
primaryColor = "#00d4aa"
backgroundColor = "#0e1117"
secondaryBackgroundColor = "#1a1f2e"
textColor = "#fafafa"
font = "monospace"Sie können auch die base auf "dark" oder "light"setzen und aus verfügbaren Schriftarten wählen: "sans serif"„ "serif"“, „ "monospace"“, „ "sans"“ oder „
Caching: st.cache_data und st.cache_resource
Weil Streamlit bei jeder Interaktion das gesamte Skript neu ausführt, wird jede teure Berechnung wiederholt – außer Sie cachen sie. Streamlit bietet zwei Caching-Dekoratoren, und die Wahl des richtigen ist entscheidend:
@st.cache_data— für Funktionen, die serialisierbare Daten (Strings, Zahlen, DataFrames, Dicts, Listen) zurückgeben. Sie hasht die Argumente der Funktion, führt die Funktion einmal aus, serialisiert das Ergebnis auf die Festplatte und liefert bei nachfolgenden Aufrufen die zwischengespeicherte Kopie aus. Jede Benutzersitzung erhält eine eigene Kopie (sicher vor mutationsübergreifenden Sitzungen).@st.cache_resource— für Funktionen, die nicht serialisierbare Objekte (Datenbankverbindungen, ML-Modelle, Dateihandles) zurückgeben. Liefert das gleiche Objekt an alle Sitzungen (geteilt). Das ist die richtige Wahl für Datenbankverbindungspools oder geladene Modellobjekte.
Ein häufiger Fehler: @st.cache_data für eine Datenbankverbindung zu verwenden. Das Verbindungsobjekt ist nicht serialisierbar und kann zwischen Sitzungen beschädigt werden. Verwenden Sie stattdessen @st.cache_resource .
@st.cache_data(ttl=3600) # refresh every hour
def load_data(url: str) -> pd.DataFrame:
return pd.read_csv(url)
@st.cache_resource
def get_db_connection():
return sqlite3.connect("data.db")Beide Dekoratoren unterstützen einen ttl -Parameter (Time-to-Live in Sekunden) für automatisches Ablaufen sowie max_entries zur Begrenzung des Speicherverbrauchs.
Sitzungsstatus: Daten über Neuausführungen hinweg speichern
Widget-Werte (Schieberegler-Positionen, Texteingaben) bleiben automatisch über Neuausführungen hinweg erhalten — Streamlit übernimmt das intern. Jede benutzerdefinierte Variable, die Sie berechnen oder speichern, benötigt jedoch st.session_state , um über Neuausführungen hinweg zu bestehen.
import streamlit as st
# Initialize
count = st.session_state.get("count", 0)
if st.button("Increment"):
st.session_state.count = count + 1
st.rerun()
st.write(f"Count: {st.session_state.get('count', 0)}")Sitzungsstatus ist ein dictionary-ähnliches Objekt, das auf jeden Browser-Tab beschränkt ist. Wichtige Eigenschaften:
- Pro Sitzung. Jeder Browser-Tab hat seinen eigenen Sitzungsstatus. Der Status von Nutzer A ist für Nutzer B unsichtbar.
- Bleibt über Neuausführungen hinweg erhalten. Werte bleiben bestehen, bis der Tab geschlossen oder der Server neu gestartet wird.
- Seitenübergreifend in Mehrseiten-Apps. Sitzungsstatus wird über alle Seiten einer Mehrseiten-App hinweg geteilt.
- Callback-Unterstützung. Widgets akzeptieren einen
on_change-Callback, der den Sitzungsstatus ändern kann, bevor die Neuausführung abgeschlossen ist.
Das Muster ist einfach: Lesen Sie zu Beginn Ihres Skripts aus st.session_state , aktualisieren Sie es bei Ereignissen, und der Status bleibt bis zum Ende der Sitzung erhalten. Bei Mehrseiten-Apps ist dies die Methode, um Daten zwischen Seiten zu teilen.
Fragmente: partielle Neuausführungen für bessere Performance
Eines der neueren Features von Streamlit (eingeführt in v1.33+) ist der @st.fragment -Dekorator. Er ermöglicht es, eine Funktion zu definieren, die unabhängig vom Rest des Skripts neu ausgeführt wird:
@st.fragment
def live_chart():
chart_data = fetch_recent_data()
st.line_chart(chart_data)
# This function reruns on its own schedule
# without triggering a full-page rerun
live_chart()
# The rest of the app stays stable
st.write("This does not rerun when the chart updates")Fragmente lösen das größte Performance-Problem in Streamlit: In einem komplexen Dashboard löst jede Widget-Interaktion eine vollständige Neuausführung aus. Mit Fragmenten lassen sich Abschnitte isolieren, die häufig aktualisiert werden (Live-Charts, Streaming-Daten), ohne die gesamte App neu auszuführen. Das ist eine erhebliche Verbesserung für Produktions-Dashboards.
Dialoge: modale Pop-ups mit @st.dialog
Streamlits @st.dialog -Dekorator erzeugt modale Dialoge, die sich über die App legen:
@st.dialog("Confirm action")
def confirm_dialog(message: str):
st.write(message)
if st.button("OK"):
st.session_state.confirmed = True
st.rerun()
if st.button("Cancel"):
st.rerun()
if st.button("Delete file"):
confirm_dialog("Are you sure you want to delete this file?")Dialoge laufen in einem separaten Ausführungskontext – der Rest der App läuft weiter, während der Dialog geöffnet ist. Das ist nützlich für Bestätigungsabläufe, mehrstufige Assistenten und jede UI, die eine fokussierte Interaktion erfordert.
Mehrseitige Apps: Navigation und Routing
Streamlit unterstützt mehrseitige Apps über zwei Mechanismen:
1. Automatische Erkennung (der einfache Weg)
Erstellen Sie ein pages/ -Verzeichnis in Ihrem Projektordner. Jede Python-Datei, die Sie dort ablegen, wird automatisch zu einer Seite im Navigationsmenü der Seitenleiste. Der Dateiname wird zum Seitentitel (Unterstriche werden in Leerzeichen umgewandelt).
my_app/
├── app.py # main entry point
└── pages/
├── 1_📊_Analytics.py
├── 2_📈_Forecasting.py
└── 3_⚙️_Settings.py2. Explizite Navigation (der kontrollierte Weg)
Für volle Kontrolle über Seitenreihenfolge, Titel und URL-Pfade verwenden Sie st.navigation() und st.Page():
import streamlit as st
pg = st.navigation([
st.Page("home.py", title="Home", url_path="home", default=True),
st.Page("settings.py", title="Preferences", url_path="settings"),
st.Page("pages/about.py", title="About Us"),
])
pg.run()Sie können auch st.switch_page("pages/my_page.py") für programmatische Navigation nutzen und st.rerun() , um die aktuelle Seite neu zu starten.
Eigene Komponenten: Streamlit über die eingebauten Funktionen hinaus erweitern
Wenn die eingebauten Widgets von Streamlit nicht ausreichen, haben Sie drei Möglichkeiten:
- Komponenten von Drittanbietern. Das Streamlit-Komponenten-Ökosystem umfasst Hunderte von Widgets, die von der Community entwickelt wurden:
streamlit-aggrid(erweiterte Datentabellen),streamlit-elements(Material-UI-Komponenten),streamlit-ace(Code-Editor),streamlit-extras(Dekorationselemente, Bäume, Mermaid-Diagramme und mehr). - Iframe-Injektion. Für schnelle Integrationen können Sie jede externe Web-App oder jedes Widget mit
st.components.v1.html(iframe_code)oderst.iframe(url)einbetten. - Eigene Komponenten entwickeln. Streamlit-Komponenten lassen sich in Python (für einfache Fälle) oder als React/TypeScript-Frontends mit Python-Backends schreiben. Das Framework stellt
declare_componentfür reine Python-Komponenten undcomponents.declare_componentfür vollständige bidirektionale Kommunikation mit einem React-Frontend bereit.
Die Streamlit-Community hat über 600 Komponenten in der offiziellen Galerie unter streamlit.io/componentsveröffentlicht. Falls Sie ein bestimmtes Widget benötigen, schauen Sie dort zuerst nach.
Datenverbindungen: Datenbanken, APIs und Geheimnisse
Streamlit bietet eine st.connection Abstraktion für die Verwaltung von Datenquellen:
st.connection("sql", type=SQLConnection)— verbindet sich mit jeder SQL-Datenbank (PostgreSQL, MySQL, SQLite, BigQuery, Snowflake, Databricks).st.connection("snowflake", type=SnowflakeConnection)— native Snowflake-Integration.- Eigene Verbindungen lassen sich durch Ableiten von
st.connections.BaseConnectionerstellen.
Für das Geheimnis-Management liest Streamlit lokal aus einer .streamlit/secrets.toml Datei (standardmäßig in .gitignore) und in der Produktion aus Umgebungsvariablen. Auf sie greifen Sie mit st.secrets["api_key"]zu.
# .streamlit/secrets.toml
db_password = "super-secret"
api_key = "sk-..."Auf Streamlit Community Cloud werden Geheimnisse über die Weboberfläche unter „Advanced Settings“ gesetzt und niemals im Code-Repository offengelegt.
Performance-Optimierung: Muster, die zählen
Das Script-Rerun-Modell bedeutet, dass Performance die zentrale technische Herausforderung in jeder nicht-trivialen Streamlit-App ist. Hier sind die Muster, die wirklich einen Unterschied machen:
- Cache aggressiv. Jede Funktion, die eine Datei liest, eine Datenbank abfragt oder eine API aufruft, sollte in
@st.cache_dataoder@st.cache_resourceeingepackt werden. Ohne das wird bei jeder Schiebereglerbewegung die Datenpipeline neu ausgeführt. - Formulare für Batch-Eingaben nutzen. Mehrere Texteingaben, Schieberegler und Selektoren in
st.form()einpacken, um Neuausführungen bis zum Klick auf „Absenden“ zu verzögern. - Fragmente für Live-Aktualisierungen verwenden. Häufig aktualisierte Abschnitte mit
@st.fragmentisolieren, damit sie unabhängig neu ausgeführt werden. - Schwere Daten lazy laden. Keinen 2-GB-Datensatz am Anfang des Skripts laden. Stattdessen in einer Funktion laden, cachen und erst aufrufen, wenn der Nutzer ihn tatsächlich braucht (z. B. nach Klick auf einen Button).
- Globale veränderliche Zustände vermeiden. Da das Skript von Grund auf neu ausgeführt wird, muss jede Mutation einer globalen Variable, die bestehen bleiben soll, in
st.session_stateabgelegt werden. Andernfalls geht die Mutation beim nächsten Neuausführen verloren. - Container für bedingtes Rendern nutzen.
st.empty()undst.container()ermöglichen, ganze Abschnitte anzuzeigen oder auszublenden, ohne die Seite umzustrukturieren.
Sicherheitsaspekte
Streamlit-Apps sind Webanwendungen, die im Internet bereitgestellt werden. Die Sicherheit liegt in Ihrer Verantwortung — mehrere Bereiche verdienen Aufmerksamkeit:
- Client-seitiger Code ist nicht geheim. Streamlit-Skripte laufen auf dem Server, aber das gerenderte HTML wird an den Browser gesendet. Geben Sie niemals API-Schlüssel, Datenbankpasswörter oder Geheimnisse direkt im Skript an. Nutzen Sie
st.secretsund Umgebungsvariablen. - Eingabebereinigung. Benutzereingaben aus Textfeldern, Datei-Uploads und Widgets sind nicht vertrauenswürdig. Bereinigen Sie sie, bevor Sie sie in SQL-Abfragen, Shell-Befehle oder Dateioperationen einsetzen.
- Sitzungsisolation. Jede Browser-Sitzung hat ihren eigenen Zustand. Ein Nutzer kann nicht auf den Sitzungszustand eines anderen zugreifen. Wenn Sie jedoch
@st.cache_resourceverwenden, wird das zwischengespeicherte Objekt geteilt — seien Sie vorsichtig mit veränderbarem gemeinsamem Zustand. - Authentifizierung. Streamlit bietet keine integrierte Authentifizierung. Für öffentlich zugängliche Apps nutzen Sie Reverse-Proxy-Authentifizierung (nginx + OAuth) oder die Drittanbieter-Bibliothek
streamlit-authenticatorfür Benutzername/Passwort-Flows. Bei Streamlit Community Cloud können Sie den Zugriff auf bestimmte E-Mail-Adressen beschränken. - unsafe_allow_html. Wenn Sie
st.markdown(..., unsafe_allow_html=True)verwenden, geben Sie niemals nutzergesteuerte Eingaben direkt weiter. Bereinigen Sie sie immer, um XSS-Angriffe zu verhindern. - Datei-Uploads. Beschränken Sie
st.file_uploaderauf bestimmte Dateitypen und Größenlimits. Hochgeladene Dateien werden in einem temporären Verzeichnis gespeichert — bereinigen Sie sie, wenn sie sensibel sind.
Deployment: von localhost zur Produktion
Streamlit bietet mehrere Deployment-Pfade mit unterschiedlichen Kompromissen:
Streamlit Community Cloud (kostenlos)
Der schnellste Weg: Repository mit GitHub verbinden und in Sekunden ausrollen. Die Community Cloud ist für öffentliche Repositories kostenlos und bietet eine kostenlose private App. Sie übernimmt HTTPS, benutzerdefinierte Domains (für kostenpflichtige Tarife) und automatisches Neudeploy nach Push. Einschränkungen: Apps gehen nach 15 Minuten Inaktivität in den Ruhezustand, und Ressourcenlimits (1 GB RAM, Basis-CPU) machen sie für rechenintensive Anwendungen ungeeignet.
Docker (selbst gehostet)
Für volle Kontrolle die App in einen Docker-Container packen:
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8501
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
ENTRYPOINT ["streamlit", "run", "app.py", \
"--server.port=8501", \
"--server.address=0.0.0.0"]Damit behalten Sie die vollständige Kontrolle über Ressourcen, Netzwerk und Skalierung. Ausrollen auf jedem Cloud-Anbieter (AWS ECS, Google Cloud Run, Azure Container Apps) oder der eigenen Infrastruktur.
Kubernetes (Enterprise)
Für großflächige Deployments unterstützt Streamlit Kubernetes. Wichtige Punkte: Jede Session benötigt eine persistente WebSocket-Verbindung (daher ist Session-Affinität relevant), und horizontales Skalieren erfordert einen gemeinsamen Cache-Backend (Redis), wenn @st.cache_data über Replikate hinweg genutzt wird.
Weitere Optionen
- Render.com — One-Click-Deploy mit kostenlosem Kontingent, automatischer Ruhezustand bei Inaktivität.
- Hugging Face Spaces — kostenloses Hosting für ML-Demos, native Streamlit-Unterstützung.
- AWS App Runner / Google Cloud Run — serverlose Container, die bei Inaktivität auf null skalieren.
- Railway / Fly.io — Platform-as-a-Service mit Unterstützung für benutzerdefinierte Domains.
Das Streamlit-Ökosystem: Bibliotheken und Werkzeuge
Der Nutzen von Streamlit vervielfacht sich in Kombination mit den richtigen Bibliotheken:
- Streamlit + Polars.
st.dataframeundst.data_editorhaben native Polars-Unterstützung — keine Konvertierung nötig. Bei großen Datensätzen passt Polars’ verzögerte Evaluierung perfekt zu Streamlits Caching, um schnelle, interaktive Exploration zu liefern. - Streamlit + Plotly.
st.plotly_chart(fig, use_container_width=True)rendert voll interaktive Plotly-Diagramme mit Zoom, Hover und Auswahl — die beliebteste Visualisierungsoption für Streamlit-Dashboards. - Streamlit + LangChain / LangGraph. Streamlit ist die de-facto-UI-Schicht für LLM-Anwendungen. Die LangChain-Dokumentation verwendet Streamlit in den meisten Beispielen. Die Kombination aus Echtzeit-Chat, Sitzungsstatus und Streaming-Antworten macht es zur natürlichen Wahl.
- Streamlit + MLflow. Experimente in MLflow tracken, Ergebnisse in Streamlit anzeigen. Ein gängiges Muster für ML-Teams: Trainieren in MLflow, Ergebnisse über ein Streamlit-Dashboard bereitstellen.
- Streamlit + PyDeck / Deck.gl.
st.map()nutzt Deck.gl im Hintergrund. Für individuelle Karten direktst.pydeck_chart()mit PyDeck-Layer-Spezifikationen verwenden. - Streamlit + DuckDB. Analytische In-Process-Datenbank. SQL-Abfragen auf großen Datensätzen direkt in Ihrer Streamlit-App ausführen — ohne separaten Datenbankserver. Ideal für Datei-Explorations-Dashboards.
- Streamlit Authenticator. Externe Bibliothek (
pip install streamlit-authenticator), die Benutzername/Passwort-Authentifizierung mit cookiebasierten Sitzungen hinzufügt. Beliebt für interne Tools.
Streamlit und die Alternativen: Dash, Gradio, Panel
Drei Konkurrenten dominieren den Python-Web-App-Bereich. Jeder bedient eine andere Nische:
Streamlit gegen Plotly Dash
Dash (von Plotly) ist der Enterprise-Schwergewicht. Es nutzt ein Callback-basiertes Modell — man definiert explizite Funktionen, die ausgelöst werden, wenn sich bestimmte Eingaben ändern — statt Streamlits Vollneuausführungsansatz. Dash gibt mehr Kontrolle, besonders bei komplexer Interaktivität, verlangt aber mehr Boilerplate. Für die meisten Data-Science- und Intern-Tool-Anwendungsfälle ist Streamlit schneller umgesetzt; für große, produktionsreife Apps mit vielen Querabhängigkeiten kann Dashs Callback-Graph im großen Maßstab vorhersehbarer sein.
Streamlit vs. Gradio
Gradio ist auf eine einzige Sache optimiert: ML-Modell-Demos. Wenn Sie eine Funktion haben, die Eingaben (Text, Bild, Audio) entgegennimmt und Ausgaben liefert, packt Gradios gr.Interface() in eine Demo-Seite mit einer Zeile. Es bietet exzellente Hugging Face-Integration (jede Gradio-App lässt sich auf HF Spaces deployen) und unterstützt über 40 Komponententypen für diverse Daten (Bilder, Audio, Video, 3D-Modelle). Streamlit ist flexibler für den Aufbau vollständiger Dashboards und mehrseitiger Apps; Gradio ist einfacher für Demos einzelner Modellfunktionen.
Streamlit vs. Panel
Panel (von HoloViz) ist das anpassbarste der vier Frameworks. Es unterstützt sowohl den Notebook-first-Ansatz (Widgets in einem Notebook definieren, als App bereitstellen) als auch einen vollständigen Skripting-Ansatz. Panels Stärke liegt in der wissenschaftlichen Visualisierung: Es integriert sich tiefgehend mit Bokeh, Matplotlib und HoloViews, und sein reaktives Programmiermodell (@param.depends) ist granularer als Streamlits Neuausführungsmodell. Der Preis dafür: Panel hat eine steilere Lernkurve und weniger Community-Unterstützung als Streamlit.
Wann man was wählt
- Streamlit wählen, wenn Sie den schnellsten Weg von einem Python-Skript zur Live-App wollen. Interne Tools, Dashboards, LLM-Demos, Datenexploration.
- Dash wählen, wenn Sie feingranulare Kontrolle über Interaktivität benötigen, eine große Produktions-App betreiben oder Enterprise-Support brauchen (Plotly bietet kommerzielle Dash-Lizenzen an).
- Gradio wählen, wenn Sie ein ML-Modell demonstrieren und den einfachstmöglichen Wrapper wollen. Ideal für Hugging Face Spaces.
- Panel wählen, wenn Sie tiefgehende wissenschaftliche Visualisierung, reaktive Programmierung benötigen und bereit sind, in das Erlernen eines komplexeren Frameworks zu investieren.
Wo Streamlit Schwächen zeigt (ehrliche Einschränkungen)
Kein Framework ist perfekt. Hier stößt Streamlits Design an echte Grenzen:
- Overhead durch vollständigen Neuaufbau. In einer komplexen App mit Dutzenden Widgets führt jede Interaktion zu einem vollständigen Neuaufbau des Skripts. Ohne Caching und Fragmente wird das zu einem echten Performanceproblem. Dashs Callbacks sind hier gezielter.
- Eingeschränkte Layout-Flexibilität. Es gibt Spalten, Seitenleiste, Tabs und Expander — das war’s im Wesentlichen. Kein Drag-and-drop, keine freie Positionierung, kein benutzerdefiniertes CSS-Framework. Wer eine hochgradig individuelle UI braucht, wird mit Streamlit kämpfen.
- Keine integrierte Authentifizierung. Für ein Framework, das stark für interne Tools genutzt wird, ist das Fehlen einer erstklassigen Authentifizierung eine überraschende Lücke. Man ist auf Drittbibliotheken oder Reverse-Proxy-Lösungen angewiesen.
- Zustandsverwaltung ist implizit. Das Neuaufbau-Modell bedeutet, dass der Zustand überall und nirgends ist. Einsteiger kämpfen oft mit der Frage „Warum wurde meine Variable zurückgesetzt?“. Es funktioniert, sobald man das Modell verinnerlicht hat, aber die Lernkurve ist real.
- WebSocket-Abhängigkeit. Streamlit hält pro Session eine WebSocket-Verbindung aufrecht. Das macht horizontales Skalieren hinter Load-Balancern schwieriger als bei einer zustandslosen HTTP-API. Für Multi-Replica-Deployments sind Sticky Sessions oder Backends mit gemeinsamem Zustand nötig.
- Keine feingranulare Reaktivität. Anders als marimo (mit Zellen-Reaktivität) oder Dash (mit Callback-Reaktivität) kennt Streamlit nur Alles-oder-nichts: Entweder wird das gesamte Skript neu aufgebaut oder ein Fragment. Eine mittlere Granularität auf Widget-Ebene gibt es nicht.
Best Practices für produktive Streamlit-Apps
- Strukturieren Sie Ihr Projekt. Packen Sie nicht alles in eine Datei. Nutzen Sie Module für Datenladen, Modell-Inferenz und Visualisierung. Importieren Sie sie in Ihr Streamlit-Skript. Das erleichtert Testen, Caching und Wiederverwendung.
- Nutzen Sie Typannotationen. Streamlit verwendet Funktionssignaturen für einige Features (Komponentenregistrierung). Doch auch bei regulären Funktionen verbessern Typannotationen die Lesbarkeit und ermöglichen IDE-Unterstützung in einem Codebase, der trügerisch einfach wirkt.
- Fixieren Sie Ihre Abhängigkeiten. Nutzen Sie ein
requirements.txtoderpyproject.tomlmit exakten Versionen. Streamlit wird häufig aktualisiert, und eine neue Version kann das Verhalten von Widgets subtil verändern. - Testen Sie Ihre Datenpipeline separat. Ihre Logik zum Laden und Transformieren von Daten sollte ohne Streamlit testbar sein. Packen Sie sie in reine Python-Funktionen, testen Sie mit pytest und rufen Sie sie erst im Streamlit-Skript auf.
- Fügen Sie Fehlerbehandlung hinzu. Nutzen Sie
st.error(),st.warning()und try/except-Blöcke, um Fehler elegant abzufangen. Eine abgestürzte Streamlit-App zeigt dem Nutzer die rohe Exception an. - Nutzen Sie den Health-Check-Endpunkt. Streamlit stellt
/_stcore/healthbereit — verwenden Sie es in Ihrem Docker-HEALTHCHECK und Monitoring. - Überwachen Sie mit integrierten Metriken. Streamlit stellt Prometheus-Metriken unter
/_stcore/metricsbereit. Integrieren Sie sie in Grafana oder Datadog für die Produktionsüberwachung.
Schnellreferenz: die Streamlit-API-Spickzettel
# App configuration
st.set_page_config(page_title="My App", layout="wide", initial_sidebar_state="expanded")
# Navigation
st.switch_page("pages/settings.py")
pg = st.navigation([st.Page("page1.py"), st.Page("page2.py")])
pg.run()
# Inputs
text = st.text_input("Name")
num = st.number_input("Age", 0, 120)
slider = st.slider("Score", 0, 100)
option = st.selectbox("Pick", ["A", "B", "C"])
files = st.file_uploader("Upload CSV", type=["csv"])
# Layout
col1, col2 = st.columns([3, 1])
with col1:
st.write("Main content")
tab1, tab2 = st.tabs(["Data", "Chart"])
with st.expander("Details"):
st.write("Hidden content")
# State
st.session_state.my_var = "value"
st.session_state.get("my_var", "default")
# Caching
@st.cache_data(ttl=3600)
def load(): ...
@st.cache_resource
def get_model(): ...
# Fragments
@st.fragment
def live_section(): ...
# Dialog
@st.dialog("Title")
def my_dialog(): ...
# Execution
st.rerun() # restart the script
st.stop() # halt execution here
# Output
st.write("Hello")
st.dataframe(df)
st.metric("Revenue", "$1.2M", "+12%")
st.pyplot(fig)
st.plotly_chart(fig)Das Fazit
Streamlit besetzt eine spezifische und wertvolle Nische: der schnellste Weg, ein Python-Daten-Skript in einen Browser zu bringen, den andere nutzen können. Sein Skript-Neulade-Modell ist zugleich seine Superkraft (bemerkenswert einfaches mentales Modell) und seine Achillesferse (Skalierungsperformance verlangt explizites Caching und Fragment-Optimierung). Für interne Tools, Dashboards, ML-Demos und Datenexplorations-Apps ist es schwer, die Geschwindigkeit von der Idee zur laufenden App zu übertreffen. Für Produktionssysteme mit komplexer Interaktivität, feingranularem State-Management oder Enterprise-Authentifizierungsanforderungen wird man irgendwann die zusätzliche Kontrolle brauchen, die Dash oder Panel bieten.
Das Streamlit-Ökosystem ist ausgereift, gut dokumentiert und wird aktiv von Snowflake gepflegt (das Streamlit 2023 übernommen hat). Mit nativer Unterstützung für Polars, Plotly und den breiteren Python-Daten-Stack sowie wachsenden Features wie Fragments, Dialogen und verbessertem Caching bleibt es einer der besten Ausgangspunkte für jeden Python-Entwickler, der Code in eine Web-App verwandeln muss.
Quellen
- Offizielle Streamlit-Dokumentation — https://docs.streamlit.io/
- Streamlit-API-Spickzettel — https://docs.streamlit.io/develop/quick-reference/cheat-sheet
- Dokumentation zum Widget-Verhalten — https://docs.streamlit.io/develop/concepts/architecture/widget-behavior
- Übersicht zum Caching — https://docs.streamlit.io/develop/concepts/architecture/caching
- Dokumentation zu Session State — https://docs.streamlit.io/develop/api-reference/caching-and-state/st.session_state
- Dokumentation zu Fragments — https://docs.streamlit.io/develop/concepts/architecture/fragments
- Dokumentation zum Datenzugriff — https://docs.streamlit.io/develop/concepts/connections/connecting-to-data
- Deployment-Tutorials — https://docs.streamlit.io/deploy/tutorials
- Streamlit-GitHub-Repository — https://github.com/streamlit/streamlit
- Streamlit-Komponenten-Galerie — https://streamlit.io/components
- Erste Schritte mit Streamlit (PyImageSearch) — https://pyimagesearch.com/2025/12/15/getting-started-with-streamlit-learn-widgets-layouts-and-caching/
weiterlesen

n8n treibt die Hälfte aller Automatisierungen im Internet an. Nennen Sie es einfach nicht Open Source.
Zwei Lager beherrschen den Bau von Agenten – entweder alles dem Modell überlassen oder jeden Pfad manuell routen. n8n besetzt die Mitte: eine Fair-Code-Leinwand mit 2.273 Integrationen, LangChain-gestützten Agenten, Preisen pro Ausführung und einer Produktions-Ops-Geschichte, die die meisten Berichte auslassen. Jede hier genannte Zahl stammt aus einer Primärquelle.
technik · 15 min · 2026-09-27
Gradio: die Nummer-eins-Schnittstelle für Machine Learning — eine Codezeile zwischen Modell und Welt
Ein Modell, das niemand nutzen kann, ist nur eine Belastung. Gradio ist die Schnittstellenebene, die Machine Learning nutzbar gemacht hat: packen Sie jede Python-Funktion mit einer Codezeile in eine Browser-UI – vom einfachen gr.Interface bis zu mehrseitigen Blocks-Apps und ChatInterface-LLM-Frontends. Dann teilen Sie es per öffentlicher URL oder stellen es auf Hugging Face Spaces bereit, der Heimat von ML-Demos. Entwickelt von Abubakar Abid an der Stanford University und betreut von Hugging Face, ist Gradio zum Standard geworden, wie die Welt KI berührt. Das ist die vollständige Übersicht.
technik · 17 min · 2026-09-13

Lokale KI ist nur eine Datei und ein Programm — so führen Sie sie selbst aus
Lokale KI klingt nach Doktortitel und einem 10.000-Dollar-Rechner. Ist sie nicht: Lokale KI ist eine Modelldatei auf Ihrer Festplatte und ein Programm, das sie ausführt — keine Cloud, keine API-Schlüssel, kein Abo. Hier sind die echten Bausteine und die vier Wege, ein Modell auf der eigenen Maschine zu betreiben, von der klickbaren App bis zum reinen Code.
technik · 14 min · 2026-09-08
