为什么用 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[col].head(top_n))
复制代码 如果用 matplotlib:- import matplotlib.pyplot as plt
- fig, ax = plt.subplots()
- ax.hist(df[col], 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[df['city'].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.,就能快速得到第一个数据应用。 |