第一章:快速入门
本章目标:用一个最小但完整的例子跑通 Bokeh,理解它适合解决什么问题,并知道下一步该学习哪些概念。
延伸阅读:本章只介绍 Bokeh 的基本用法。
ColumnDataSource的深入讲解见第二章 2.2;Figure与Glyph的关系见第二章 2.3;三层接口的详细说明见第二章 2.4;输出选项的完整讨论见第八章;如果你想先建立对不同运行方式的整体认识,也可以先浏览第八章 8.1和第七章 7.1。
1.1 从一个需求开始
假设你有一组销售数据,想要展示每天的销售额变化。用 Matplotlib 可以很快画出一张静态图:
import matplotlib.pyplot as plt
days = [1, 2, 3, 4, 5]
sales = [100, 150, 120, 180, 200]
plt.plot(days, sales)
plt.savefig("sales.png")
这类图片很适合放进论文、报告或幻灯片。但如果你的需求变成下面这样,静态图片就不够方便了:
- 想在浏览器里缩放和平移,查看局部细节
- 想把鼠标悬停在点上,显示具体数值
- 想生成一个可以直接分享的 HTML 文件
- 想把图表嵌入现有 Web 页面或数据应用
- 想后续扩展为可筛选、可联动、可实时更新的仪表板
这就是 Bokeh 的典型使用场景:
用 Python 构建原生 Web 交互图表,并输出到浏览器、HTML 文件、Notebook 或 Web 应用中。
需要注意的是,Matplotlib 也有交互式后端,并不是“完全不能交互”。Bokeh 的优势在于:它以浏览器和 Web 交互为核心设计,生成的是由 BokehJS 渲染的交互式图表,更适合分享、嵌入和构建数据应用。
1.2 安装与环境
系统要求
本教程面向 Bokeh 3.x 编写。建议使用:
- Python 3.10 或更高版本
- 推荐 Python 3.11+,以获得更好的生态兼容性和运行性能
- 一个现代浏览器,例如 Chrome、Firefox、Edge 或 Safari
基础安装
如果你使用 pip:
pip install bokeh
验证安装:
python -c "import bokeh; print(bokeh.__version__)"
如果你使用 conda:
conda install bokeh
可选依赖
Bokeh 的基础绘图不需要安装额外依赖。但有些功能需要额外包,例如导出 PNG/SVG、使用 Notebook 小组件或处理更复杂的应用场景。
常见选择:
# 安装 Bokeh 的常用可选依赖
pip install "bokeh[all]"
# 如果你需要在 Jupyter 中使用更完整的 Bokeh 小组件支持
pip install jupyter_bokeh
提示:如果你只是想在 Notebook 中显示普通 Bokeh 图表,通常先从
output_notebook()开始即可;如果遇到 JupyterLab 显示或小组件相关问题,再安装jupyter_bokeh。
1.3 第一个 Bokeh 图表
下面用同一组销售数据生成一个交互式 HTML 图表:
from bokeh.plotting import figure, output_file, show
days = [1, 2, 3, 4, 5]
sales = [100, 150, 120, 180, 200]
output_file("sales.html", title="销售趋势")
p = figure(
title="销售趋势",
x_axis_label="日期",
y_axis_label="销售额",
width=700,
height=400,
tools="pan,wheel_zoom,box_zoom,reset,save",
active_scroll="wheel_zoom",
)
p.line(days, sales, line_width=2, legend_label="销售额")
p.scatter(days, sales, size=8, legend_label="销售额")
show(p)
运行后,Bokeh 会生成 sales.html,并在浏览器中打开它。你可以:
- 使用滚轮缩放图表
- 拖拽平移查看不同区域
- 使用框选缩放查看局部范围
- 点击重置按钮恢复初始视图
- 点击保存按钮下载当前图表为图片
这段代码可以拆成三步理解:
output_file("sales.html"):指定输出目标是一个 HTML 文件figure(...):创建一张图,并配置标题、坐标轴、尺寸和工具栏p.line(...)、p.scatter(...):向图中添加具体图形show(p):保存并打开图表
这就是 Bokeh 最常见的工作流:
准备数据 → 创建 Figure → 添加 Glyph → 输出或展示图表。
其中 Figure 是整张图的容器,line 和 scatter 添加的是具体图形元素,也就是 Bokeh 中常说的 Glyph。这些概念会在第二章展开。
1.4 加上悬停提示
交互图表最常见的需求之一是:鼠标移动到数据点上时显示更多信息。
这时推荐使用 ColumnDataSource。它是 Bokeh 中最重要的数据结构之一,可以把数据组织成“按列存储的表”。
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.plotting import figure, output_file, show
source = ColumnDataSource(data={
"day": [1, 2, 3, 4, 5],
"sales": [100, 150, 120, 180, 200],
"note": ["周一", "周二", "周三", "周四", "周五"],
})
output_file("sales_with_hover.html", title="销售趋势")
p = figure(
title="销售趋势",
x_axis_label="日期",
y_axis_label="销售额",
width=700,
height=400,
tools="pan,wheel_zoom,box_zoom,reset,save",
active_scroll="wheel_zoom",
)
p.line("day", "sales", source=source, line_width=2)
p.scatter("day", "sales", source=source, size=8)
hover = HoverTool(tooltips=[
("日期", "@day"),
("销售额", "@sales"),
("说明", "@note"),
])
p.add_tools(hover)
show(p)
注意这段代码中的两个变化:
- 图形方法里不再直接写列表,而是写列名,例如
"day"和"sales" HoverTool通过@day、@sales、@note读取同一行中的字段
如果你后续要做筛选、联动、回调或实时更新,ColumnDataSource 会变得非常重要。现在只需要先记住一句话:
简单图表可以直接传列表;一旦涉及交互和多字段数据,优先使用
ColumnDataSource。
1.5 在 Jupyter 中使用
如果你在 Jupyter Notebook 或 JupyterLab 中学习 Bokeh,可以把输出目标切换到 Notebook:
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
output_notebook()
p = figure(title="Notebook 中的 Bokeh 图表", width=600, height=350)
p.line([1, 2, 3, 4, 5], [100, 150, 120, 180, 200], line_width=2)
p.scatter([1, 2, 3, 4, 5], [100, 150, 120, 180, 200], size=8)
show(p)
常见输出方式如下:
| 输出方式 | 适用场景 | 特点 |
|---|---|---|
output_notebook() | Jupyter 开发和教学 | 图表直接显示在 Notebook 单元格中 |
output_file() | 生成独立 HTML 文件 | 适合本地查看、分享和归档 |
save() | 程序化保存 | 只保存文件,不自动打开浏览器 |
show() | 快速预览 | 根据当前输出目标显示图表 |
components() | 嵌入 Web 页面 | 返回可嵌入网页的 HTML/JavaScript 片段 |
更完整的输出方式会在第八章介绍。
1.6 先建立一个概念:Bokeh 的四种运行模式
很多初学者一开始最容易混淆的,不是 figure() 或 HoverTool,而是:
同样是 Bokeh 代码,为什么有的可以直接生成 HTML,有的必须用
bokeh serve运行?
你可以先把 Bokeh 的使用方式分成四类:
| 运行模式 | 典型入口 | 适用场景 | 关键特点 |
|---|---|---|---|
| standalone HTML | output_file() / save() / show() | 分享单个交互图表 | 生成独立 HTML,交互主要在浏览器端完成 |
| Notebook | output_notebook() | 教学、探索分析 | 图表直接显示在 Notebook 单元格中 |
| Bokeh Server | bokeh serve app.py --show | Python 回调、实时更新、状态同步 | 浏览器和 Python 进程持续通信 |
| embed 到现有 Web 页面 | components()、file_html()、server_document() | Flask、Django、已有前端页面 | 适合把 Bokeh 接入更大的 Web 系统 |
初学阶段你最常用的是前两种:
- standalone HTML
- Notebook
它们的共同点是:
你写 Python 代码生成图表对象,Bokeh 再把这些对象转换成浏览器可以理解的内容,由 BokehJS 在前端渲染和交互。
而 Bokeh Server 的不同点在于:
- 浏览器中的交互事件会继续传回 Python
- Python 回调函数可以重新计算数据并推回前端
- 因此它更适合筛选器、实时刷新、复杂业务逻辑
你现在可以先记住一个简单判断:
- 只想生成交互图表文件 → 先用 standalone HTML
- 在 Notebook 里学习和试验 → 用 Notebook
- 需要 Python 回调或实时更新 → 用 Bokeh Server
- 需要嵌入现有网站 → 学第八章的 embed 方式
这一点非常重要,因为它会直接影响后面章节中代码应该如何运行:
- 第六章的
CustomJS示例很多可以直接用于 standalone HTML - 第七章的 Python 回调示例必须通过
bokeh serve运行 - 第八章会系统讲解 standalone、Notebook、embed 等输出方式的差异
1.7 Bokeh 适合什么,不适合什么
Bokeh 不是要替代所有可视化工具。不同库有不同的优势。
| 需求场景 | 推荐工具 | 理由 |
|---|---|---|
| 论文配图、静态报告 | Matplotlib | 出版质量高,控制细节丰富 |
| 快速统计图表 | Seaborn | 默认样式美观,适合统计分析 |
| 交互式 Web 图表 | Bokeh | 原生浏览器交互,输出方式灵活 |
| 仪表板和数据应用 | Bokeh Server | 支持 Python 回调、状态同步和实时更新 |
| 快速探索性分析 | Plotly Express | API 简洁,上手快 |
Bokeh 的主要优势包括:
- 使用 Python 编写图表逻辑
- 输出 HTML,便于分享和嵌入
- 浏览器端由 BokehJS 渲染,交互体验自然
- 与 NumPy、Pandas 等 Python 数据生态配合良好
- 既能画单张图,也能扩展为完整的 Bokeh Server 应用
- 支持多种输出方式,包括 HTML、Notebook、Web 组件和图片导出
如果你的目标是“一张精致的静态出版图”,Matplotlib 可能更合适;如果你的目标是“可以在浏览器中探索的数据图表”,Bokeh 就非常适合。
1.8 Bokeh 的三层接口
Bokeh 提供多个层次的接口。快速入门阶段不需要全部掌握,但你应该知道它们各自解决什么问题。
第一层:bokeh.plotting
这是最常用的高级绘图接口,适合大部分日常图表。
from bokeh.plotting import figure, show
p = figure(title="plotting 接口示例")
p.line([1, 2, 3], [4, 5, 6], line_width=2)
p.scatter([1, 2, 3], [4, 5, 6], size=8)
show(p)
你在本章前面使用的 figure()、p.line()、p.scatter() 都属于这一层。
第二层:bokeh.models
这一层提供更细粒度的模型对象,例如数据源、工具、坐标轴、范围、颜色映射、回调等。你通常会把它和 bokeh.plotting 一起使用。
from bokeh.models import ColumnDataSource, HoverTool
from bokeh.plotting import figure, show
source = ColumnDataSource(data={
"x": [1, 2, 3],
"y": [4, 5, 6],
"label": ["A", "B", "C"],
})
p = figure(title="models 接口示例")
p.scatter("x", "y", source=source, size=12)
p.add_tools(HoverTool(tooltips=[
("标签", "@label"),
("x", "@x"),
("y", "@y"),
]))
show(p)
这类写法会在交互、联动和数据更新中频繁出现。
第三层:bokeh.io、bokeh.embed 和相关输出接口
这一层主要控制图表如何输出、保存或嵌入。
from bokeh.embed import components
from bokeh.plotting import figure
p = figure(title="嵌入示例")
p.line([1, 2, 3], [4, 5, 6])
script, div = components(p)
components(p) 会返回一段 <script> 和一个 <div>,方便你把 Bokeh 图表嵌入到 Flask、Django 或其他 Web 页面中。
选择建议:
- 日常画图:优先使用
bokeh.plotting - 需要悬停、筛选、联动、回调:结合使用
bokeh.models - 需要控制 HTML、Notebook、导出或嵌入:学习
bokeh.io和bokeh.embed - 需要实时应用和服务端状态:学习 Bokeh Server
三层接口的更完整说明见第二章 2.4。
1.9 本章小结
本章你已经完成了 Bokeh 的第一轮入门:
- 知道 Bokeh 的核心定位是 Python 驱动的 Web 交互可视化
- 安装并验证了 Bokeh 环境
- 用
figure()创建了第一张交互式图表 - 使用
output_file()和show()生成并打开 HTML 文件 - 初步接触了
ColumnDataSource和HoverTool - 了解了 Bokeh 与 Matplotlib、Seaborn、Plotly 等工具的差异
- 知道了 Bokeh 的常用接口层次
接下来建议阅读第二章:核心概念。理解 ColumnDataSource、Figure、Glyph 和 Document 之后,你会更容易掌握后续的交互、布局和 Bokeh Server。
1.10 常见坑
坑 1:把 standalone HTML 和 Bokeh Server 混为一谈
这是初学者最常见的问题。
如果你写的是:
output_file()/save()/show()output_notebook()
那么你通常得到的是 standalone 文档。这类图表可以有缩放、平移、悬停等浏览器端交互,但 Python 回调不会继续运行。
如果你写的是:
curdoc()on_change()add_periodic_callback()
那么通常说明你已经进入 Bokeh Server 场景,需要使用 bokeh serve 运行。关于这一点,见第七章。
坑 2:一开始就忽略 ColumnDataSource
简单示例里直接传列表没有问题,但只要你需要下面这些能力:
- 悬停显示更多字段
- 多个图共享数据
- 做选择联动
- 做数据更新
就应该尽早切换到 ColumnDataSource。它会在第二章详细展开。
坑 3:以为 show() 就等于“部署完成”
show() 更像是“快速预览”:
- 在脚本里,通常会打开浏览器
- 在 Notebook 里,通常会直接内联显示
但这不等于你已经掌握了分享、嵌入、导出、集成到 Web 框架中的方法。相关内容请继续看第八章。
坑 4:还没区分输出方式,就急着查交互为什么不工作
如果你发现“图显示出来了,但某些回调没反应”,先不要急着怀疑 API。
先问自己两个问题:
- 我现在运行的是 standalone / Notebook,还是 Bokeh Server?
- 我使用的是前端交互(例如
HoverTool、CustomJS),还是 Python 回调?
很多问题其实不是代码错了,而是运行方式和代码模型不匹配。
下一步建议
建议按下面顺序继续:
- 阅读第二章:核心概念,重点理解
ColumnDataSource - 阅读第八章:输出选项,建立更完整的运行模式认识
- 准备学习 Python 回调前,再阅读第七章:Bokeh Server 进阶