Dash 是 Plotly 公司出品的 Python 数据应用框架,构建在 Flask + React 之上,让纯 Python 开发者无需写一行 JavaScript 就能搭出可交互的 Web Dashboard。24K stars、MIT 协议、11 年迭代,是 ”Python 全栈 BI” 的代名词。
写在前面
数据可视化库有一堆(plotly / matplotlib / bokeh / altair),但当你需要 把图变成完整的 Web 应用——有用户、有权限、能部署上线——Python 生态里能打的就两个:Dash 和 Streamlit。
Dash 是 2015 年 Plotly 公司推出的,定位是 ” 生产级 ML & 数据 Web 应用 ”,Flask + React + Plotly.js 三件套,纯 Python 写 UI。跟它同期 / 后出的 Streamlit 更 ” 原型友好 ”,但 Dash 在企业级特性(认证 / 多页面 / 模块化)上更扎实。
本期把这个老牌框架的 ” 现在版 ” 讲清楚——v4.4.1 已发布、Pages 模块化、background 回调性能优化、长连接 WebSocket(ws-always-on)解决状态管理。
一、它解决什么问题
一句话卖点 :Python 开发者写 ML/ 数据 Web 应用, 零 JavaScript、零前端构建,完整 Flask + React 全栈体验。
| 维度 | 信息 |
|---|---|
| 项目名 | Dash |
| 作者 / 维护 | Plotly 公司官方维护(T4rk1n / chriddyp / alexcjohnson 核心 3 人) |
| Stars | 24,371 |
| Forks | 2,314 |
| License | MIT |
| 语言 | Python + TypeScript + HTML + CSS |
| 创建时间 | 2015-04-10(11 年常青树) |
| 最新版本 | v4.4.1(2026-07-21)/ v4.4.0(2026-07-03) |
| 最近更新 | 2026-08-07(3 天前 ws-always-on fix) |
| Open Issues | 539 |
| Python 要求 | >= 3.9 |
| 核心依赖 | Flask<3.2>=1.0.4、Werkzeug<3.2、plotly>=5.0.0、janus>=1.0.0 |
二、核心能力:声明式 + 反应式
2.1 两种 API 风格
| API | 适合场景 | 特点 |
|---|---|---|
| Dash 2.x 现代 API | 90% 项目 | 装饰器风格 @callback、声明式 layout |
| Dash 1.x 经典 API | 复杂状态管理 | @app.callback 原生、底层控制更强 |
# Dash 2.x 极简示例
import dash
from dash import dcc, html, Input, Output, callback
app = dash.Dash(__name__)
app.layout = html.Div([dcc.Dropdown(["A", "B", "C"], id="dd"),
dcc.Graph(id="graph"),
])
@callback(Output("graph", "figure"), Input("dd", "value"))
def update(value):
return px.bar(x=[value], y=[1])
app.run(debug=True)
2.2 组件生态
| 类别 | 组件 |
|---|---|
| 核心 | dcc.Dropdown、dcc.Slider、dcc.Graph、dcc.Input、dcc.Tabs |
| HTML | html.Div、html.H1、html.Table(React 元素映射) |
| 企业级扩展 | Dash Bootstrap Components / Dash Mantine Components / Dash AG Grid |
| 数据表 | Dash AG Grid(最强,支持百万行虚拟滚动) |
| 图表 | 任何 plotly.js 图直接嵌入 |
2.3 高级能力
- 回调系统:
@callback装饰器自动建立 Input → Output 依赖 - 多页面:
dash.register_page("page-name")模块化路由 - 后台回调:
@callback(..., background=True)长任务异步化 - 状态管理:
dcc.Store组件 + WebSocket 同步浏览器端状态(v4.4 新 ws-always-on 改进) - 持久化:
diskcache集成用于回调缓存
三、差异化能力:为什么是 Dash 而不是 Streamlit
这是最常被问的问题。两者都是 Python 数据 Web 应用框架,但定位不同:
| 维度 | Dash | Streamlit |
|---|---|---|
| 定位 | 生产级 / 企业应用 | 原型 / 快速 demo |
| API 风格 | 声明式 layout(UI 代码 → DOM 树) | 命令式(每次交互重跑整个脚本) |
| 状态管理 | dcc.Store + 回调图 |
st.session_state |
| 多页面 | dash.register_page() 完整路由 |
简陋 pages 机制 |
| 回调粒度 | 控件级别(只触发相关回调) | 全脚本重跑 |
| 大数据 | ✅ AG Grid 虚拟滚动百万行 | ⚠️ 全脚本重跑慢 |
| 性能 | ⭐⭐⭐⭐(细粒度更新) | ⭐⭐⭐(重跑) |
| 学习曲线 | ⭐⭐⭐(需懂回调图) | ⭐⭐⭐⭐⭐(最易上手) |
| 部署 | Flask/Python/Docker | Streamlit Cloud / Docker |
| 认证 | 完整(Enterprise 支持 LDAP/SAML/SSO) | 社区版需 hack |
| 主题 | Bootstrap / Mantine 自定义 | 主题有限 |
| Plotly 集成 | ✅ 原生 dcc.Graph | ✅ st.plotly_chart |
| Stars | 24K | 38K |
| 公司维护 | Plotly(商业 + 开源双轨) | Snowflake(2022 收购) |
核心判断:
–
选 Dash:做生产应用 / 多页面 Dashboard / 复杂交互 / 大数据表 / 企业认证
–
选 Streamlit:做 ML demo / 实验性原型 / 团队 Python 基础一般
四、对比:跟同类框架比好在哪
| 维度 | Dash | Streamlit | Gradio | Panel (Bokeh) | Shiny (R) |
|---|---|---|---|---|---|
| 底层 | Flask + React | Tornado + 自研 | FastAPI + 自研 | Bokeh Server | R + HTML |
| 图表 | ⭐ plotly 全套 | 多种 | 简化版 | Bokeh 库 | ggplot2 |
| 大数据表 | ⭐⭐⭐⭐⭐ AG Grid | ⭐⭐ | ❌ | ⭐⭐⭐ | ⭐⭐ |
| ML 生态 | ⭐⭐⭐⭐ Dash AG Grid + Plotly | ⭐⭐⭐⭐ ML 集成好 | ⭐⭐⭐⭐⭐ ML demo 之王 | ⭐⭐⭐ | ⭐⭐ |
| 学习曲线 | 中 | 低 | 极低 | 中 | 中 |
| 企业级 | ⭐⭐⭐⭐⭐ Enterprise | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 移动端响应 | ✅ | ✅ | ⚠️ | ✅ | ⚠️ |
| 多语言 | Python + R | Python only | Python only | Python + R | R only |
| License | MIT | Apache-2.0 | Apache-2.0 | BSD | AGPL/Commercial |
五、实战:3 步跑通完整 Dashboard
Step 1:安装 + 最小应用
pip install dash plotly pandas
# app.py
import dash
from dash import dcc, html, Input, Output
import plotly.express as px
df = px.data.gapminder()
app = dash.Dash(__name__)
app.layout = html.Div([html.H1("Gapminder Dashboard"),
dcc.Dropdown(
id="continent",
options=[{"label": c, "value": c} for c in df["continent"].unique()],
value="Asia",
clearable=False,
),
dcc.Graph(id="graph"),
])
@app.callback(Output("graph", "figure"), Input("continent", "value"))
def update(continent):
dff = df[df["continent"] == continent]
return px.line(dff, x="year", y="lifeExp", color="country")
if __name__ == "__main__":
app.run(debug=True, port=8050)
python app.py
# 打开 http://127.0.0.1:8050
Step 2:升级为多页面应用
my_dash_app/
├── app.py
├── pages/
│ ├── overview.py # 自动注册为 /overview
│ └── detail.py # 自动注册为 /detail
# pages/overview.py
import dash
from dash import html
dash.register_page(__name__)
layout = html.Div("Overview page")
# app.py 顶部加:app = dash.Dash(__name__, use_pages=True)
Step 3:部署到生产
pip install gunicorn
gunicorn app:server -w 4 -b 0.0.0.0:8050
# 或 Docker / Heroku / Dash Enterprise
需要认证?安装 Dash Enterprise 或自己加 Flask-Login 中间件。
六、风险与坑
- 回调复杂度爆炸:超过 50 个回调的项目会变成 ” 回调图地狱 ”,需要
dash.register_page模块化 + 拆多个app,单 app 不超过 30 个回调。 - 回调性能:同步回调阻塞主线程,长任务必须用
@callback(..., background=True, run=PoolExecutor(max_workers=4))异步。 - WebSocket 长连接稳定性:v4.4 之前存在 WebSocket 断连后状态丢失问题(
ws-always-onPR #3941 已修,2026-08-07 合并),升级 v4.4.1+。 - 大数据图表卡顿:和 plotly 同源问题,万级散点要
go.Scattergl走 WebGL。 - 移动端需要手动响应式:Dash 不像 Bootstrap 默认响应式,需用
dbc.Col+xs/md/lg显式声明断点。 - Flask 版本锁:依赖
Flask<3.2,如果团队其他服务用 Flask 3.2+,会有版本冲突(虽然 PIP 装不同 venv 通常能解决)。 - Dash Enterprise 商业化分离风险:Plotly 公司主营商业版(认证、部署、监控),开源版核心功能完备但企业级功能需要付费。这是商业双轨策略,开源版仍可用,要关注 Plotly 商业策略调整。
七、总结
三个最值得装的理由:
- Python 全栈 BI 最成熟方案——24K stars + 11 年迭代 + Plotly 公司维护,是 ”Python 写 ML/Dashboard Web 应用 ” 的代名词,比 Streamlit 更适合生产环境,比 Gradio 更适合复杂交互
- 零 JavaScript 真能落地——HTML 组件 + 装饰器回调,真不用写一行前端代码,对 Python 团队是降维打击
- 生态完整 + 企业级路线清晰——AG Grid / Bootstrap Components / Mantine Components / Plotly 全套组件齐全,Dash Enterprise 提供官方付费路径(非必需但有兜底)
一句话 :如果你的团队全是 Python 背景、要做 生产级 Dashboard / ML 后台, 先试一周 Dash + AG Grid,比 Flask + 自己撸前端快 10 倍。
参考
- GitHub: https://github.com/plotly/dash
- PyPI: https://pypi.org/project/dash/
- 官方文档: https://dash.plotly.com/getting-started
- App Gallery: https://dash.gallery
- Dash Enterprise: https://plotly.com/dash/
- Dash Bootstrap Components: https://dash-bootstrap-components.opensource.faculty.ai/
- Dash AG Grid: https://dash.plotly.com/dash-ag-grid
- 飞熊 plotly 调研(姊妹篇):https://east196.cn/?p=298