下面是一个简单数据分析:
df = pd.read_csv("销售数据.csv")result = df.groupby("地区").agg({"销售额": "sum", "利润": "mean"})print(result)输出:

但这个输出内容你怎么给你的老板看呢?截图通过微信发给你老板?
实际上他想要一个能打开的链接、能筛选的日期、能下载的表格,一个可视化界面。
这不是你一个人的困境。每一个做数据分析的 Python 开发者都卡在「分析能力满分,交付能力零分」的断层上——你能写出复杂的数据管道,但没法让业务方自己探索数据。
「Streamlit 就是为填这个断层而生的。」 它的设计哲学非常简单:你只需要写 Python,它帮你生成 Web 界面。
上面代码仅需简单改造就能变成一个漂亮的 Web 应用:
import streamlit as stimport pandas as pdst.title("销售数据看板")df = pd.read_csv("销售数据.csv")st.dataframe(df) # 可排序、可筛选的交互式表格st.bar_chart(df.groupby("地区")["销售额"].sum())通过下面shell安装、运行
pip install streamlit # 安装streamlit run app.py # 运行浏览器自动打开 http://localhost:8501。 你看到的不是一个终端输出,而是一个「完整的 Web 应用」——有标题、有表格(可以点击列头排序)、有柱状图。你没写一行 HTML。

Streamlit 是一个开源的 Python 库,能够让你「纯用 Python 代码」快速构建和分享数据 Web 应用。不需要 HTML、CSS 或 JavaScript,几分钟就能把一个 Python 脚本变成可交互的网页应用。
它尤其适合数据科学家、机器学习工程师和需要快速做原型演示的开发者。 你写的是线性 Python 脚本,但它呈现的是一个有状态的交互式 Web 应用。
环境要求:Python 3.8 ~ 3.13。
pip install streamlit安装完成后,验证是否成功:
streamlit hello这会启动一个本地服务,并在浏览器中打开 Streamlit 的官方演示页面。

创建一个 app.py 文件:
import streamlit as stimport pandas as pdimport numpy as npst.title("我的第一个 Streamlit 应用")st.write("Hello, Streamlit!")# 生成一些随机数据并绘制折线图chart_data = pd.DataFrame( np.random.randn(20, 3), columns=["A", "B", "C"])st.line_chart(chart_data)在终端中运行:
streamlit run app.py
文本组件负责将信息直观地呈现给用户。不同于普通的 print(),Streamlit 的文本组件会渲染在浏览器中,并支持丰富的格式和层级结构。
st.title("这是一级标题") # 最大号标题st.header("这是二级标题") # 中号标题st.subheader("这是三级标题") # 小号标题st.markdown("支持 **Markdown** 语法")st.text("纯文本内容")st.code("print('Hello')", language="python") # 代码块,带语法高亮st.caption("这是一段说明性小字")st.latex(r"e^{i\pi} + 1 = 0") # LaTeX 公式输出:

数据展示组件是 Streamlit 作为数据分析工具的核心优势。它们不仅展示数据,还提供了交互能力,帮助用户快速洞察规律。
data = {"姓名": ["张三", "李四", "王五"],"年龄": [25, 30, 28],"城市": ["北京", "上海", "广州"]}df = pd.DataFrame(data)st.dataframe(df) # 可交互的表格(支持排序、缩放)st.table(df) # 静态表格st.json(data) # JSON 格式化展示st.metric("温度", "24°C", delta="1.5°C") # 指标卡片,delta 表示变化量输出:

Streamlit 内置了几种常用图表,也支持 Matplotlib、Plotly、Altair 等第三方图表库。
import pandas as pdimport numpy as npimport streamlit as stdata = {"姓名": ["张三", "李四", "王五"],"年龄": [25, 30, 28],"城市": ["北京", "上海", "广州"],"薪资": [15000, 18000, 16000]}df = pd.DataFrame(data)# st.map 需要 latitude / longitude 列(或 lat / lon)location_data = pd.DataFrame({"latitude": [39.9042, 31.2304, 23.1291, 22.5431, 30.5728],"longitude": [116.4074, 121.4737, 113.2644, 114.0579, 104.0668],"city": ["北京", "上海", "广州", "深圳", "成都"]})import matplotlib.pyplot as plt# 内置图表(基于 Altair)# 只选数值列做图表,避免字符串列报错df_chart = df.set_index("姓名")[["年龄", "薪资"]]st.line_chart(df_chart) # 折线图st.area_chart(df_chart) # 面积图st.bar_chart(df_chart) # 柱状图st.scatter_chart(df, x="年龄", y="薪资") # 散点图st.map(location_data) # 地图(需 latitude/longitude 列)# Matplotlibfig, ax = plt.subplots()ax.plot([1, 2, 3], [1, 4, 2])st.pyplot(fig)# Plotly(交互式图表)import plotly.express as pxfig = px.scatter(df, x="年龄", y="薪资")st.plotly_chart(fig, use_container_width=True)产生多种图表, 输出:

输入组件是 Streamlit 的灵魂。用户每次操作控件(如滑动、点击、输入),整个 Python 脚本都会从上到下重新执行,变量值自动更新为控件当前状态。这种 “数据流驱动” 的模式极大地简化了后端逻辑。
# 文本输入name = st.text_input("请输入你的名字", value="")password = st.text_input("请输入密码", type="password")comment = st.text_area("请输入评论", height=150)# 数字输入age = st.number_input("请输入年龄", min_value=0, max_value=150, value=25, step=1)score = st.slider("评分", min_value=0.0, max_value=10.0, value=5.0, step=0.5)# 选择类option = st.selectbox("选择城市", ["北京", "上海", "广州", "深圳"])options = st.multiselect("选择爱好", ["阅读", "运动", "音乐", "旅游"], default=["阅读"])checked = st.checkbox("我同意条款")color = st.color_picker("选择颜色", "#00FFAA")# 日期与时间date = st.date_input("选择日期")time = st.time_input("选择时间")# 文件上传uploaded_file = st.file_uploader("上传文件", type=["csv", "txt", "png", "jpg"])# 按钮if st.button("点击我"): st.success(f"你好,{name}!")# 下载按钮st.download_button( label="下载 CSV", data=df.to_csv(index=False).encode("utf-8"), file_name="data.csv", mime="text/csv")输出:

优秀的应用不仅功能完备,还应该给用户清晰的操作反馈。Streamlit 提供了一套完整的反馈机制,涵盖成功、提示、警告、错误和进度追踪。
st.success("操作成功!") # 绿色提示条st.info("这是一条信息提示") # 蓝色提示条st.warning("请注意!") # 黄色警告条st.error("出错了!") # 红色错误条# 进度条与等待with st.spinner("处理中,请稍候..."): time.sleep(2)st.success("完成!")progress_bar = st.progress(0)for i in range(100): time.sleep(0.01) progress_bar.progress(i + 1)# 吐司通知st.toast("任务已完成!", icon="🎉")# 全局异常捕获try:1 / 0except Exception as e: st.exception(e) # 展开显示完整的 traceback输出:

默认情况下,Streamlit 组件按顺序垂直排列。布局组件让你能够像画板一样自由组织页面结构,将应用从“长文档”升级为“仪表盘”。
# 侧边栏with st.sidebar: st.header("侧边栏") option = st.radio("导航", ["首页", "数据", "关于"])# 列布局col1, col2, col3 = st.columns(3)with col1: st.metric("收入", "¥12,000", "8%")with col2: st.metric("支出", "¥5,800", "-12%")with col3: st.metric("净利润", "¥6,200", "21%")# 容器container = st.container(border=True)container.write("这是带边框的容器")# 可展开区域with st.expander("点击查看详情"): st.write("这里是详细内容")# 多标签页tab1, tab2, tab3 = st.tabs(["概况", "图表", "数据"])with tab1: st.write("概况页面内容")with tab2: st.line_chart(np.random.randn(30, 3))with tab3: st.dataframe(df)
理解 Streamlit 的执行模型(每次交互全量重跑)是性能优化的前提。如果没有缓存,每次滑块拖动或按钮点击都会重新加载几十 MB 的 CSV 或重新训练模型,应用会变得极其卡顿。
@st.cache_data 会缓存函数返回值,脚本重新运行时如果参数未变则直接返回缓存结果,避免重复加载数据或重复计算。
# 告诉 Streamlit:如果 URL 没变,就不重新读取@st.cache_data defload_data(url):# 模拟耗时加载,实际项目中为 pd.read_csv(url)return pd.read_csv(url)# 第一次运行会下载并缓存,后续滑块变动时直接返回缓存df = load_data("https://example.com/large-dataset.csv")# 带 TTL 的缓存(适用于动态数据)@st.cache_data(ttl=600) # 10 分钟后自动刷新deffetch_live_data():return requests.get("https://api.example.com/live").json()Streamlit 的“重跑”机制虽然简化了逻辑,但也带来了一个棘手问题:本地变量会在每次交互后重置。比如你写了一个 count = 0,点击按钮 count += 1,页面刷新后 count 又被设回 0。这就无法实现“计数器”、“购物车”、“多步骤表单向导”等需要跨交互记忆的场景。
页面导航:用 st.session_state.page 记录当前所在页面,点击侧边栏菜单时切换。
表单向导:分步收集用户信息,每一步将输入保存到 session_state,最后统一提交。
防重复提交:通过 st.session_state.submitted 布尔值控制按钮的可用状态。
Streamlit 默认在每次交互时从头执行脚本。当你需要跨交互保存变量时(比如计数器),就需要 st.session_state:
# 初始化计数器(确保首次访问时存在)if"count"notin st.session_state: st.session_state.count = 0# 计数按钮 - 每次点击触发 +1if st.button("➕ 点击 +1"): st.session_state.count += 1st.metric("点击次数", st.session_state.count)# 重置按钮 - 将计数归零if st.button("🔄 重置"): st.session_state.count = 0# 小技巧:利用 session_state 实现“首次运行”标记if"first_run"notin st.session_state: st.session_state.first_run = True st.info("👋 欢迎首次访问!")else: st.write(f"你已经访问了 {st.session_state.count} 次")# 清除特定状态(用于退出登录或清空表单)# del st.session_state["user_info"]st.session_state 本质上是一个字典,但支持属性访问(st.session_state.count 等价于 st.session_state["count"])。
本文主要讲解streamlit的基本安装及简单示例,着重介绍了该项目能够使用的各种组件,现在 你可以通过各组件构建简单的web应用了。