Streamlit构建交互式Web应用实战:控件缓存与销售看板
为什么用 Streamlit 把 Python 脚本变成 Web 应用很多 Python 工程师用 pandas 分析、matplotlib 画图后,只能截图或放 Jupyter Notebook。要让别人打开网页使用,通常要补 HTML/CSS/JavaScript 和 Flask/Django 后端。Streamlit 的目标是让开发者只用 Python 写交互式 Web 应用,不用前端代码,保存脚本后页面自动热更新。它适合数据分析师、算法工程师、运维人员把脚本快速变成可分享原型。
环境准备与版本验证
Streamlit 是纯 Python 库,支持 Python 3.8+。建议虚拟环境隔离:
python -m venv .venv
source .venv/bin/activate# Windows 使用对应 Scripts 目录下的 activate
pip install streamlit
验证安装:
# check_version.py
import streamlit as st
# 打印当前 Streamlit 版本,确认安装成功
print('Streamlit 版本:', st.__version__)
执行 streamlit run check_version.py,会启动本地服务并自动打开浏览器,默认地址 http://localhost:8501。后续示例都使用该端口。
最小可运行示例与重跑机制
# app.py
import streamlit as st
st.title('我的第一个 Streamlit 应用')
st.write('你好,这是用纯 Python 写出来的网页!')
age = st.slider('请选择你的年龄', 0, 120, 25)
st.write('你选择的年龄是:', age)
运行 streamlit run app.py。拖动滑块时数字立即变化。关键机制是:每次交互,整个脚本会从上到下重新执行,Streamlit 再把新输出映射到界面。理解这一点对后面处理状态和缓存很重要。
控件、布局、会话状态与缓存
输入控件会返回当前值:
name = st.text_input('你的名字', '张三')
agree = st.checkbox('我同意条款')
option = st.selectbox('选择城市', ['北京', '上海', '广州'])
clicked = st.button('点我提交')
布局方面,st.sidebar 放侧边栏,st.columns 做并排:
st.sidebar.title('筛选条件')
threshold = st.sidebar.slider('阈值', 0, 100, 50)
col1, col2 = st.columns(2)
col1.metric('销量', 1280)
col2.metric('增长率', '12%')
脚本每次重跑,普通变量不会跨重跑保存。需要 st.session_state:
if 'count' not in st.session_state:
st.session_state.count = 0
if st.button('加一'):
st.session_state.count += 1
st.write('当前计数:', st.session_state.count)
加载大文件或训练模型很慢时,用 @st.cache_data 按入参缓存函数结果:
@st.cache_data
def load_data(path):
import pandas as pd
return pd.read_csv(path)
文件上传与图表联动
Streamlit 对 pandas、matplotlib、Plotly 等生态原生友好。上传 CSV、出图、滑块过滤的组合:
import pandas as pd
import streamlit as st
uploaded = st.file_uploader('上传一个 CSV 文件', type='csv')
if uploaded is not None:
df = pd.read_csv(uploaded)
st.dataframe(df.head(20))
numeric_cols = df.select_dtypes('number').columns.tolist()
if numeric_cols:
col = st.selectbox('选择要画图的数值列', numeric_cols)
top_n = st.slider('显示前 N 行', 5, 50, 10)
st.line_chart(df.head(top_n))
如果用 matplotlib:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.hist(df, bins=20)
st.pyplot(fig)
实战:迷你销售看板完整代码
# dashboard.py
import pandas as pd
import streamlit as st
@st.cache_data
def load_data(uploaded_file):
return pd.read_csv(uploaded_file)
st.set_page_config(page_title='销售看板', layout='wide')
st.title('迷你销售看板')
uploaded = st.file_uploader('上传销售数据 CSV(需含 city、amount、date 列)', type='csv')
if uploaded is None:
st.info('请先上传一个 CSV 文件开始使用。')
st.stop()
df = load_data(uploaded)
df['date'] = pd.to_datetime(df['date'])
cities = st.sidebar.multiselect(
'选择城市',
df['city'].unique(),
default=list(df['city'].unique())[:3]
)
filtered = df.isin(cities)]
col1, col2 = st.columns(2)
total = filtered['amount'].sum()
col1.metric('总销售额', f'{total:,.0f}')
col2.metric('订单数', len(filtered))
st.subheader('销售额趋势')
st.line_chart(filtered.set_index('date')['amount'].resample('D').sum())
st.subheader('城市汇总')
st.dataframe(filtered.groupby('city')['amount'].sum().reset_index())
运行 streamlit run dashboard.py,上传包含 city、amount、date 列的 CSV,即可得到一个可筛选、可联动的销售看板。代码里 st.stop() 用于没有上传文件时停止后续渲染,@st.cache_data 避免重复解析同一上传文件。
常见报错与排查
坑 1:ModuleNotFoundError: No module named 'streamlit'
原因:安装环境和运行环境不是同一个 Python;或者根本没安装。解决:核对 which python、pip show streamlit 的路径,虚拟环境下先 activate 再运行。
坑 2:端口 8501 被占用,自动跳到 8502/8503
启动时可能提示 Port 8501 is already in use, trying 8502。原因通常是上次服务未关闭。解决:关闭旧进程,或显式指定端口:
streamlit run app.py --server.port 8503
坑 3:点击 st.button 后状态没记住
按钮点击只在当次重跑返回 True,之后会重置,普通变量无法跨重跑保存。解决:用 st.session_state 持久化,或用 st.checkbox、st.toggle 这类天然带状态的控件替代。
下一步
需要缓存数据库连接或机器学习模型时,可以使用 @st.cache_resource;需要多页面时,把页面拆到 pages/ 目录;需要分享时,可用 Streamlit Community Cloud 免费托管。把现有 pandas 脚本外面套一层 st.,就能快速得到第一个数据应用。
Re: Streamlit构建交互式Web应用实战:控件缓存与销售看板
感谢分享,这篇从最小示例一路讲到缓存和销售看板,思路很清楚,尤其把脚本重跑机制单独拎出来讲很关键。很多人第一次用 Streamlit 时,拖一下滑块发现整个脚本又跑一遍,容易懵,理解 session_state 和 @st.cache_data 后就顺多了。销售看板里侧边栏多选城市、两列 metric 展示总额和订单数,这个组合也很实用。 一个小建议:@st.cache_data 如果直接缓存 file_uploader 返回的对象,最好在函数里先取 uploaded_file.getvalue() 再用 BytesIO 读,或者把文件字节内容作为参数传进去,这样不同 CSV 不容易串缓存,也能避免文件指针位置带来的问题。另外上传后可以先校验 city、amount、date 这几列是否齐全,缺列时用提示信息拦住,而不是让 pandas 直接报错,用户体验会更好。 首帖最后好像截断在 st.subhe,期待把后面的图表联动和完整看板部分补全。Re: Streamlit构建交互式Web应用实战:控件缓存与销售看板
这篇挺适合当 Streamlit 入门实战,把“每次交互脚本会从上到下重跑”和 session_state、cache_data 放在一起讲,确实能帮新手少踩很多坑。销售看板的思路也很顺,上传 CSV、缓存读取、侧边栏多选城市、两列指标卡,基本能直接套到自己的数据上。 有两个小地方可以再稳一点:一是 file_uploader 返回的对象在重跑时不一定稳定,@st.cache_data 直接缓存 uploaded_file 可能命中不了,改成缓存 uploaded_file.getvalue() 或先解析成 DataFrame 再缓存会更可靠;二是看板里直接取 city、amount、date,如果用户传的 CSV 列名不对会直接报错,可以先检查列名,再用 st.error 提示需要这几列,日期解析也可以加 errors='coerce' 并过滤无效行。这样体验会更好。最后代码到 st.subhe 那里好像还没贴完,如果后面还有分组图表,期待补全。Re: Streamlit构建交互式Web应用实战:控件缓存与销售看板
感谢分享,写得挺系统,从环境准备、最小示例到控件、布局、会话状态和缓存,再到文件上传和销售看板,基本把 Streamlit 做数据应用的主线串起来了。最认同的一点是把“每次交互整个脚本重新执行”单独强调出来,这个机制不弄清楚,后面用 session_state 和 cache_data 很容易踩坑。销售看板那段也很实用,侧边栏多选城市、两列指标卡、上传 CSV 后过滤和展示,都是很常见的看板需求,st.stop() 的用法也很干净。 不过结尾好像停在 st.subhe,感觉后面应该还有按日期或城市分组的图表没写完?如果继续补,建议加上 CSV 缺列或 date 解析失败时的友好提示,再顺带说明一下 cache_data 对上传文件的缓存行为,这样别人换文件测试时不容易被旧缓存绕进去。整体很有帮助,收藏了。
页:
[1]