The fastest way to build and share data apps
Application configuration, performance optimization through caching decorators, session state management, and utility functions for app lifecycle control. These capabilities help you build performant, stateful applications with proper configuration management.
Configure global app settings and appearance.
def set_page_config(
page_title: str = None,
page_icon: str = None,
layout: str = "centered",
initial_sidebar_state: str = "auto",
menu_items: dict = None
) -> None:
"""
Configure the page settings (must be first Streamlit command).
Parameters:
- page_title: Title shown in browser tab
- page_icon: Icon shown in browser tab (emoji or image URL)
- layout: Page layout ("centered" or "wide")
- initial_sidebar_state: Initial sidebar state ("auto", "expanded", "collapsed")
- menu_items: Custom menu items dictionary
"""import streamlit as st
# Configure page (must be first Streamlit command)
st.set_page_config(
page_title="My Data App",
page_icon="📊",
layout="wide",
initial_sidebar_state="expanded",
menu_items={
'Get Help': 'https://docs.streamlit.io/',
'Report a bug': "https://github.com/myorg/myapp/issues",
'About': "This is a demo app built with Streamlit!"
}
)
st.title("Welcome to My App")Access and modify Streamlit's configuration system.
def get_option(key: str):
"""
Get the value of a configuration option.
Parameters:
- key: Configuration key (e.g., "theme.primaryColor")
Returns:
The current value of the configuration option
"""
def set_option(key: str, value) -> None:
"""
Set the value of a configuration option.
Parameters:
- key: Configuration key (e.g., "theme.primaryColor")
- value: New value for the configuration option
"""import streamlit as st
# Get current configuration
current_theme = st.get_option("theme.base")
st.write(f"Current theme: {current_theme}")
# Set configuration options
st.set_option("theme.primaryColor", "#FF6B6B")
st.set_option("theme.backgroundColor", "#FFFFFF")
# Common configuration options
st.write("Available config categories:")
st.write("- theme.*: UI theme settings")
st.write("- server.*: Server configuration")
st.write("- browser.*: Browser behavior")
st.write("- logger.*: Logging configuration")Traditional caching decorator for expensive computations.
@cache(persist: bool = False, allow_output_mutation: bool = False, suppress_st_warning: bool = False, hash_funcs: dict = None, max_entries: int = None, ttl: float = None, show_spinner: bool = True)
def cached_function():
"""
Decorator for caching function results (legacy).
Parameters:
- persist: Whether to persist cache across sessions
- allow_output_mutation: Whether to allow mutation of cached results
- suppress_st_warning: Whether to suppress Streamlit warnings
- hash_funcs: Custom hash functions for parameters
- max_entries: Maximum number of cache entries
- ttl: Time-to-live in seconds
- show_spinner: Whether to show spinner during computation
"""import streamlit as st
import pandas as pd
import time
@st.cache
def load_data(file_path):
"""Load data with caching to avoid repeated file reads."""
time.sleep(2) # Simulate expensive operation
return pd.read_csv(file_path)
@st.cache(ttl=3600) # Cache for 1 hour
def fetch_api_data(api_url):
"""Fetch data from API with time-based cache expiration."""
# Simulate API call
time.sleep(1)
return {"data": "api_result", "timestamp": time.time()}
# Use cached functions
data = load_data("data.csv")
api_result = fetch_api_data("https://api.example.com/data")
st.dataframe(data)
st.json(api_result)New caching decorators with improved performance and features.
@experimental_memo(persist: str = None, show_spinner: bool = True, suppress_st_warning: bool = False, max_entries: int = None, ttl: float = None)
def memo_function():
"""
Decorator for caching data and computations (experimental).
Parameters:
- persist: Persistence mode ("disk" or None)
- show_spinner: Whether to show spinner during computation
- suppress_st_warning: Whether to suppress Streamlit warnings
- max_entries: Maximum number of cache entries
- ttl: Time-to-live in seconds
"""
@experimental_singleton(show_spinner: bool = True, suppress_st_warning: bool = False)
def singleton_function():
"""
Decorator for creating singleton objects (experimental).
Parameters:
- show_spinner: Whether to show spinner during initialization
- suppress_st_warning: Whether to suppress Streamlit warnings
"""import streamlit as st
import pandas as pd
import numpy as np
@st.experimental_memo
def expensive_computation(n):
"""Expensive computation with memo caching."""
# Simulate heavy computation
result = np.random.rand(n, n).dot(np.random.rand(n, n))
return result
@st.experimental_singleton
def get_database_connection():
"""Create singleton database connection."""
# Simulate database connection setup
class MockDB:
def __init__(self):
self.connected = True
def query(self, sql):
return pd.DataFrame({"result": [1, 2, 3]})
return MockDB()
# Use modern caching
matrix = expensive_computation(100)
db = get_database_connection()
st.write(f"Matrix shape: {matrix.shape}")
st.dataframe(db.query("SELECT * FROM table"))Manage user session data that persists across app reruns.
session_state: SessionStateProxy
# Access via st.session_state
class SessionStateProxy:
"""Session state management interface."""
def __getitem__(self, key: str) -> Any:
"""Get session state value."""
def __setitem__(self, key: str, value: Any) -> None:
"""Set session state value."""
def __contains__(self, key: str) -> bool:
"""Check if key exists in session state."""
def __delitem__(self, key: str) -> None:
"""Delete session state key."""import streamlit as st
# Initialize session state
if "counter" not in st.session_state:
st.session_state.counter = 0
if "user_data" not in st.session_state:
st.session_state.user_data = {}
# Use session state with widgets
col1, col2, col3 = st.columns(3)
with col1:
if st.button("Increment"):
st.session_state.counter += 1
with col2:
if st.button("Decrement"):
st.session_state.counter -= 1
with col3:
if st.button("Reset"):
st.session_state.counter = 0
st.write(f"Counter: {st.session_state.counter}")
# Form data persistence
with st.form("user_form"):
name = st.text_input("Name", value=st.session_state.user_data.get("name", ""))
age = st.number_input("Age", value=st.session_state.user_data.get("age", 0))
if st.form_submit_button("Save"):
st.session_state.user_data["name"] = name
st.session_state.user_data["age"] = age
st.success("Data saved to session!")
# Display all session state (for debugging)
with st.expander("Session State Debug"):
st.write(st.session_state)Securely access application secrets and configuration.
secrets: SecretsProxy
# Access via st.secrets
class SecretsProxy:
"""Secrets management interface."""
def __getitem__(self, key: str) -> Any:
"""Get secret value."""
def __contains__(self, key: str) -> bool:
"""Check if secret exists."""import streamlit as st
# Access secrets (configured in .streamlit/secrets.toml)
db_password = st.secrets["database"]["password"]
api_key = st.secrets["api_key"]
# Use secrets safely
if "database" in st.secrets:
connection_string = f"postgresql://user:{st.secrets.database.password}@localhost/db"
st.success("Database configured")
else:
st.error("Database secrets not found")
# Example secrets.toml structure:
st.code("""
# .streamlit/secrets.toml
api_key = "your-api-key-here"
[database]
host = "localhost"
port = 5432
username = "user"
password = "secret-password"
""", language="toml")Control application execution flow and provide user feedback.
def stop() -> NoReturn:
"""
Stop execution of the Streamlit script.
Raises:
StreamlitAPIException: Always (stops execution)
"""
def balloons() -> DeltaGenerator:
"""Display falling balloons animation."""
def snow() -> DeltaGenerator:
"""Display falling snow animation."""
def progress(value: float) -> DeltaGenerator:
"""
Display a progress bar.
Parameters:
- value: Progress value between 0.0 and 1.0
Returns:
DeltaGenerator: Progress bar object that can be updated
"""
def spinner(text: str = "In progress...") -> ContextManager[None]:
"""
Display a spinner with text during long operations.
Parameters:
- text: Text displayed next to spinner
Returns:
Context manager for use with 'with' statement
"""
def echo(code_location: str = "above") -> ContextManager[None]:
"""
Display code while executing it.
Parameters:
- code_location: Where to show code ("above" or "below")
Returns:
Context manager for code echoing
"""import streamlit as st
import time
# Celebration animations
if st.button("Celebrate!"):
st.balloons()
st.success("Congratulations!")
if st.button("Winter Theme"):
st.snow()
st.info("Let it snow!")
# Progress bar
progress_bar = st.progress(0)
status_text = st.empty()
for i in range(100):
progress_bar.progress(i + 1)
status_text.text(f'Progress: {i+1}%')
time.sleep(0.01)
status_text.text('Operation completed!')
# Spinner for long operations
with st.spinner('Loading data...'):
time.sleep(3) # Simulate long operation
data = [1, 2, 3, 4, 5]
st.success('Data loaded!')
st.write(data)
# Echo code execution
with st.echo():
# This code will be displayed and executed
x = 10
y = 20
result = x + y
st.write(f"The result is {result}")
# Conditional stop
user_input = st.text_input("Enter 'stop' to halt execution:")
if user_input.lower() == 'stop':
st.error("Execution stopped by user!")
st.stop()
st.write("This will only show if execution wasn't stopped")Access and modify URL query parameters.
def experimental_get_query_params() -> Dict[str, List[str]]:
"""
Get the current query parameters from the URL.
Returns:
Dictionary mapping parameter names to lists of values
"""
def experimental_set_query_params(**kwargs) -> None:
"""
Set query parameters in the URL.
Parameters:
- **kwargs: Parameter names and values to set
"""import streamlit as st
# Get current query parameters
query_params = st.experimental_get_query_params()
st.write("Current query parameters:", query_params)
# Use query parameters to set initial state
if "page" in query_params:
initial_page = query_params["page"][0]
else:
initial_page = "home"
# Widget that updates URL
page = st.selectbox("Select page:", ["home", "data", "settings"],
index=["home", "data", "settings"].index(initial_page))
# Update query parameters when selection changes
if page != initial_page:
st.experimental_set_query_params(page=page)
# Multiple parameters
filter_type = st.selectbox("Filter:", ["all", "active", "inactive"])
sort_by = st.selectbox("Sort by:", ["name", "date", "priority"])
# Update multiple parameters
st.experimental_set_query_params(
page=page,
filter=filter_type,
sort=sort_by
)
st.write(f"Current page: {page}")
st.write(f"Filter: {filter_type}, Sort: {sort_by}")Programmatically control script execution flow.
def experimental_rerun() -> NoReturn:
"""
Rerun the current script (experimental).
Raises:
StreamlitAPIException: Always (triggers rerun)
"""import streamlit as st
# Button that triggers rerun
if st.button("Refresh Data"):
# Clear any cached data if needed
st.cache.clear()
# Trigger script rerun
st.experimental_rerun()
# Conditional rerun based on state
if st.session_state.get("needs_refresh", False):
st.session_state.needs_refresh = False
st.experimental_rerun()Access user information in deployed apps.
experimental_user: UserInfoProxy
class UserInfoProxy:
"""User information access interface (experimental)."""
@property
def email(self) -> str:
"""Get user's email address (if available)."""import streamlit as st
# Access user information (only works in deployed apps)
try:
user_email = st.experimental_user.email
st.write(f"Welcome, {user_email}!")
except:
st.write("User information not available (local development)")
# Conditional features based on user
if hasattr(st.experimental_user, 'email'):
if "@company.com" in st.experimental_user.email:
st.info("You have admin access")
admin_section = st.checkbox("Show admin panel")
if admin_section:
st.write("Admin controls would go here")@st.cache or @st.experimental_memo for expensive data loading@st.experimental_singleton for database connections and ML modelsst.session_state to maintain state across rerunsst.secrets for sensitive configuration datasuppress_st_warning=True to silence caching warnings in productionInstall with Tessl CLI
npx tessl i tessl/pypi-streamlit@1.16.0