- Spec files
pypi-streamlit
Describes: pkg:pypi/streamlit@1.49.x
- Description
- A faster way to build and share data apps
- Author
- tessl
- Last updated
state-caching.md docs/
1# State and Caching23State management, caching mechanisms, and performance optimization tools for maintaining application state and improving performance through intelligent data persistence.45## Capabilities67### Session State Management89Persistent state storage across user interactions and app reruns.1011```python { .api }12# Session state proxy object13session_state: SessionStateProxy1415# Access patterns:16# st.session_state.key = value # Set value17# value = st.session_state.key # Get value18# st.session_state["key"] = value # Dictionary-style set19# value = st.session_state["key"] # Dictionary-style get20# del st.session_state.key # Delete key21# "key" in st.session_state # Check existence22# st.session_state.clear() # Clear all state23```2425### Query Parameters Management2627URL query parameter handling for shareable application state.2829```python { .api }30# Query parameters proxy object31query_params: QueryParamsProxy3233# Access patterns:34# st.query_params.key = value # Set parameter35# value = st.query_params.key # Get parameter36# st.query_params["key"] = value # Dictionary-style set37# value = st.query_params["key"] # Dictionary-style get38# del st.query_params.key # Delete parameter39# st.query_params.clear() # Clear all parameters40# dict(st.query_params) # Convert to dictionary41```4243### Data Caching4445Cache function execution results to improve performance and reduce redundant computations.4647```python { .api }48def cache_data(func=None, *, ttl=None, max_entries=None, show_spinner=True, persist=None, experimental_allow_widgets=False, hash_funcs=None, max_entries_per_session=None, validate=None):49"""50Function decorator to cache the result of function calls.5152Parameters:53- func (callable): Function to cache (auto-filled when used as decorator)54- ttl (float): Time to live in seconds (None for no expiration)55- max_entries (int): Maximum number of cached entries (None for unlimited)56- show_spinner (bool): Show spinner while function executes57- persist (bool): Persist cache across app restarts (experimental)58- experimental_allow_widgets (bool): Allow widgets inside cached function59- hash_funcs (dict): Custom hash functions for parameters60- max_entries_per_session (int): Maximum entries per session61- validate (callable): Function to validate cached values6263Returns:64callable: Decorated function with caching capability65"""66```6768### Resource Caching6970Cache global resources like database connections, models, and expensive objects.7172```python { .api }73def cache_resource(func=None, *, ttl=None, max_entries=None, show_spinner=True, validate=None, experimental_allow_widgets=False, hash_funcs=None):74"""75Function decorator to cache global resources.7677Parameters:78- func (callable): Function to cache (auto-filled when used as decorator)79- ttl (float): Time to live in seconds (None for no expiration)80- max_entries (int): Maximum number of cached resources (None for unlimited)81- show_spinner (bool): Show spinner while function executes82- validate (callable): Function to validate cached resources83- experimental_allow_widgets (bool): Allow widgets inside cached function84- hash_funcs (dict): Custom hash functions for parameters8586Returns:87callable: Decorated function with resource caching capability88"""89```9091### Legacy Caching9293Deprecated caching decorator for backward compatibility.9495```python { .api }96def cache(func=None, **kwargs):97"""98Legacy caching decorator (deprecated).99100Note: This function is deprecated. Use st.cache_data or st.cache_resource instead.101102Parameters:103- func (callable): Function to cache104- **kwargs: Cache configuration options105106Returns:107callable: Decorated function with caching108"""109```110111## Usage Examples112113### Basic Session State114115```python116import streamlit as st117118# Initialize session state119if 'count' not in st.session_state:120st.session_state.count = 0121122if 'user_name' not in st.session_state:123st.session_state.user_name = ''124125# Display current state126st.write(f"Count: {st.session_state.count}")127st.write(f"User: {st.session_state.user_name}")128129# Modify state with buttons130col1, col2, col3 = st.columns(3)131132with col1:133if st.button('Increment'):134st.session_state.count += 1135136with col2:137if st.button('Decrement'):138st.session_state.count -= 1139140with col3:141if st.button('Reset'):142st.session_state.count = 0143144# Update user name145new_name = st.text_input('Enter your name:', value=st.session_state.user_name)146if new_name != st.session_state.user_name:147st.session_state.user_name = new_name148```149150### Advanced Session State Patterns151152```python153# Session state with complex data structures154if 'shopping_cart' not in st.session_state:155st.session_state.shopping_cart = []156157if 'user_preferences' not in st.session_state:158st.session_state.user_preferences = {159'theme': 'light',160'notifications': True,161'language': 'en'162}163164# Add item to cart165def add_to_cart(item, price):166st.session_state.shopping_cart.append({167'item': item,168'price': price,169'quantity': 1170})171172# Display cart173st.subheader("Shopping Cart")174if st.session_state.shopping_cart:175for i, item in enumerate(st.session_state.shopping_cart):176col1, col2, col3 = st.columns([2, 1, 1])177with col1:178st.write(item['item'])179with col2:180st.write(f"${item['price']:.2f}")181with col3:182if st.button('Remove', key=f'remove_{i}'):183st.session_state.shopping_cart.pop(i)184st.rerun()185186total = sum(item['price'] for item in st.session_state.shopping_cart)187st.write(f"**Total: ${total:.2f}**")188else:189st.write("Cart is empty")190191# Add new items192st.subheader("Add Items")193item_name = st.text_input("Item name:")194item_price = st.number_input("Price:", min_value=0.01, format="%.2f")195196if st.button("Add to Cart") and item_name:197add_to_cart(item_name, item_price)198st.success(f"Added {item_name} to cart!")199```200201### Query Parameters for Shareable State202203```python204# Initialize from query parameters205if 'page' not in st.query_params:206st.query_params.page = 'home'207208if 'filter' not in st.query_params:209st.query_params.filter = 'all'210211# Navigation that updates URL212st.sidebar.title("Navigation")213214pages = ['home', 'analytics', 'settings']215current_page = st.sidebar.selectbox(216"Select page:",217pages,218index=pages.index(st.query_params.page) if st.query_params.page in pages else 0219)220221# Update query params when page changes222if current_page != st.query_params.page:223st.query_params.page = current_page224st.rerun()225226# Filters that update URL227filters = ['all', 'active', 'inactive']228current_filter = st.sidebar.selectbox(229"Filter:",230filters,231index=filters.index(st.query_params.filter) if st.query_params.filter in filters else 0232)233234if current_filter != st.query_params.filter:235st.query_params.filter = current_filter236st.rerun()237238# Display content based on query params239st.title(f"Page: {st.query_params.page}")240st.write(f"Filter: {st.query_params.filter}")241242# Show shareable URL243st.info(f"Share this URL: {st.query_params}")244```245246### Data Caching247248```python249import pandas as pd250import time251import requests252253@st.cache_data254def load_data(url):255"""Load data from URL with caching."""256st.info(f"Loading data from {url}...")257response = requests.get(url)258return pd.read_csv(response.content)259260@st.cache_data(ttl=300) # Cache for 5 minutes261def expensive_computation(n):262"""Simulate expensive computation with TTL."""263st.info("Running expensive computation...")264time.sleep(2) # Simulate processing time265return sum(i**2 for i in range(n))266267@st.cache_data(max_entries=10)268def process_data(data, operation):269"""Process data with limited cache size."""270st.info(f"Processing data with {operation}...")271if operation == 'sum':272return data.sum()273elif operation == 'mean':274return data.mean()275elif operation == 'max':276return data.max()277else:278return data279280# Use cached functions281st.subheader("Cached Data Loading")282283# This will only run once per URL284try:285df = load_data("https://raw.githubusercontent.com/datasets/iris/master/data/iris.csv")286st.dataframe(df.head())287except Exception as e:288st.error(f"Failed to load data: {e}")289290# Expensive computation with TTL291st.subheader("Cached Computation")292n = st.slider("Computation size:", 1000, 10000, 5000)293result = expensive_computation(n)294st.write(f"Result: {result}")295296# Data processing with limited cache297if 'df' in locals():298operation = st.selectbox("Operation:", ['sum', 'mean', 'max'])299numeric_cols = df.select_dtypes(include=['number']).columns300if len(numeric_cols) > 0:301processed = process_data(df[numeric_cols[0]], operation)302st.write(f"Result: {processed}")303```304305### Resource Caching306307```python308import sqlite3309from datetime import datetime310311@st.cache_resource312def init_database():313"""Initialize database connection (cached resource)."""314st.info("Initializing database connection...")315conn = sqlite3.connect(':memory:')316317# Create sample table318conn.execute('''319CREATE TABLE users (320id INTEGER PRIMARY KEY,321name TEXT,322email TEXT,323created_at TIMESTAMP324)325''')326327# Insert sample data328sample_users = [329('Alice', 'alice@example.com'),330('Bob', 'bob@example.com'),331('Charlie', 'charlie@example.com')332]333334for name, email in sample_users:335conn.execute(336'INSERT INTO users (name, email, created_at) VALUES (?, ?, ?)',337(name, email, datetime.now())338)339340conn.commit()341return conn342343@st.cache_resource344def load_model():345"""Load ML model (simulated)."""346st.info("Loading machine learning model...")347time.sleep(1) # Simulate model loading time348return {"model_type": "random_forest", "accuracy": 0.95, "loaded_at": datetime.now()}349350# Use cached resources351st.subheader("Cached Database Connection")352db = init_database()353354# Query database355users = db.execute('SELECT * FROM users').fetchall()356st.write("Users in database:")357for user in users:358st.write(f"- {user[1]} ({user[2]})")359360st.subheader("Cached Model")361model = load_model()362st.json(model)363```364365### Cache Management366367```python368# Cache inspection and management369st.subheader("Cache Management")370371col1, col2, col3 = st.columns(3)372373with col1:374if st.button("Clear Data Cache"):375st.cache_data.clear()376st.success("Data cache cleared!")377378with col2:379if st.button("Clear Resource Cache"):380st.cache_resource.clear()381st.success("Resource cache cleared!")382383with col3:384if st.button("Clear All Caches"):385st.cache_data.clear()386st.cache_resource.clear()387st.success("All caches cleared!")388389# Custom hash function example390@st.cache_data(391hash_funcs={pd.DataFrame: lambda df: df.shape},392show_spinner="Processing dataframe..."393)394def analyze_dataframe(df, analysis_type):395"""Analyze dataframe with custom hashing."""396time.sleep(1) # Simulate analysis397398if analysis_type == "describe":399return df.describe()400elif analysis_type == "info":401return f"Shape: {df.shape}, Columns: {list(df.columns)}"402else:403return "Unknown analysis type"404405# Use function with custom hashing406if 'df' in locals():407analysis = st.selectbox("Analysis type:", ["describe", "info"])408result = analyze_dataframe(df, analysis)409st.write(result)410```411412### State Persistence Patterns413414```python415# Multi-step form with state persistence416if 'form_step' not in st.session_state:417st.session_state.form_step = 1418419if 'form_data' not in st.session_state:420st.session_state.form_data = {}421422st.subheader(f"Multi-step Form - Step {st.session_state.form_step}/3")423424# Progress bar425progress = st.session_state.form_step / 3426st.progress(progress)427428if st.session_state.form_step == 1:429st.write("**Personal Information**")430name = st.text_input("Name:", value=st.session_state.form_data.get('name', ''))431email = st.text_input("Email:", value=st.session_state.form_data.get('email', ''))432433if st.button("Next") and name and email:434st.session_state.form_data.update({'name': name, 'email': email})435st.session_state.form_step = 2436st.rerun()437438elif st.session_state.form_step == 2:439st.write("**Preferences**")440theme = st.selectbox("Theme:", ["Light", "Dark"],441index=["Light", "Dark"].index(st.session_state.form_data.get('theme', 'Light')))442notifications = st.checkbox("Enable notifications",443value=st.session_state.form_data.get('notifications', False))444445col1, col2 = st.columns(2)446with col1:447if st.button("Back"):448st.session_state.form_step = 1449st.rerun()450451with col2:452if st.button("Next"):453st.session_state.form_data.update({'theme': theme, 'notifications': notifications})454st.session_state.form_step = 3455st.rerun()456457elif st.session_state.form_step == 3:458st.write("**Review & Submit**")459st.json(st.session_state.form_data)460461col1, col2 = st.columns(2)462with col1:463if st.button("Back"):464st.session_state.form_step = 2465st.rerun()466467with col2:468if st.button("Submit"):469st.success("Form submitted successfully!")470st.balloons()471# Reset form472st.session_state.form_step = 1473st.session_state.form_data = {}474```475476### Cache Validation477478```python479@st.cache_data(480validate=lambda cached_value: len(cached_value) > 0,481ttl=60482)483def get_api_data(endpoint):484"""Fetch API data with validation."""485# Simulate API call486time.sleep(0.5)487if endpoint == "valid":488return ["item1", "item2", "item3"]489else:490return [] # This will invalidate the cache491492# Use validated cache493endpoint = st.selectbox("API Endpoint:", ["valid", "empty"])494data = get_api_data(endpoint)495496if data:497st.success(f"Got {len(data)} items from cache/API")498st.write(data)499else:500st.warning("No data available (cache invalidated)")501```