设置开发环境#
Bokeh 项目由两个主要组件组成:用 Python 编写的 Bokeh 包源代码,以及用 TypeScript 编写的 BokehJS 客户端库。
因此,您需要设置两个环境来为 Bokeh 贡献代码:一个 Python 环境和一个 TypeScript 环境。本章将引导您完成设置完整开发环境所需的所有步骤。
1. 检查基本要求#
安装或更新 Git#
Bokeh 源代码存储在 Git 源代码控制存储库中。在 Bokeh 上工作的第一步是在您的系统上安装或更新 Git。
有不同的方法可以做到这一点,具体取决于您使用的是 Windows、OSX 还是 Linux。要在任何平台上安装 Git,请参阅 Pro Git 书籍 的 安装 Git 部分。
如果您以前从未使用过 Git,可以在 Git 文档 中找到一些初学者教程和资源的链接。
安装或更新 conda#
处理 Bokeh 代码库需要安装一些不是 Python 包的软件包。例如,用于 TypeScript 开发的 Node.js 或用于测试和导出的 Selenium。
为了能够在一个地方管理 Python 和非 Python 依赖项,Bokeh 使用 conda 包管理器。conda
是适用于 Windows、macOS 和 Linux 的免费 Anaconda Python 发行版的一部分。Conda 为您创建和管理虚拟环境。因此,您不需要 venv
、virtualenv
或 pipenv
等工具。虽然从技术上讲,可以在没有 conda
的情况下手动安装所有依赖项,但本指南假设您已安装 conda
。
要在您的系统上安装或更新 Conda,请参阅 Conda 文档 中的 安装。
注意
如果您的系统上已经安装了 conda
,请确保通过运行以下命令将其更新到最新版本
conda update -n base -c defaults conda
2. Fork 和克隆存储库#
Bokeh 项目的源代码托管在 GitHub 上,位于 bokeh/bokeh。
除非您是 @bokeh/dev 团队成员,否则您首先需要创建 Bokeh 主存储库的分支。在创建分支时,请确保取消选中将复制限制为特定分支(例如“仅复制 branch-3.2 分支”)的复选框。有关创建分支的更多信息,请参阅 GitHub 帮助 中的 Fork 存储库。
接下来,将您要处理的 Bokeh 存储库版本克隆到硬盘驱动器上的本地文件夹中。使用 git clone
或按照 GitHub 帮助 中 克隆分支存储库 的说明进行操作。
克隆存储库会在您的文件系统位置创建一个 bokeh
目录。此本地 bokeh
目录在本文档的其余部分称为源检出。
在继续之前,有必要使用以下命令将 Bokeh 存储库添加为另一个上游存储库
git remote add upstream [email protected]:bokeh/bokeh.git
git fetch upstream
git remote add upstream https://github.com/bokeh/bokeh.git
git fetch upstream
3. 创建 conda 环境#
您刚刚克隆到本地硬盘驱动器的 Bokeh 存储库包含 测试环境文件,位于 conda 文件夹中。这些文件中包含自动创建基本开发环境所需的所有必要信息。
在源检出目录的根级别使用 conda env create
来设置环境并安装所有必要的软件包。“测试”环境文件按 Python 版本进行版本控制。
例如,要为 Python 3.10 安装环境,请调用
conda env create -n bkdev -f conda/environment-test-3.10.yml
注意
使用 conda -n bkdev
选项将 bkdev
设为环境的名称。本章和本指南中的所有其他章节都假设这是您环境的名称。
然后,激活环境
conda activate bkdev
注意
要更新您的本地环境,请使用 conda env update --name bkdev -f conda/<environment file>
。每当测试环境中的依赖项发生更改时,都需要更新您的本地环境。例如,当主 Bokeh 存储库中的环境文件更新或您切换分支以处理不同的问题时,可能会发生这种情况。
4. 安装 Node 包#
构建 BokehJS 还需要使用 Node 包管理器 (npm) 安装 JavaScript 依赖项。如果您已遵循 上述说明,conda
已将必要的 npm
和 node.js
包安装到您的系统中。
Bokeh 通常需要最新主要版本的 npm
。要全局安装最新版本,请从源检出目录的顶层开始,并运行以下命令
cd bokehjs
npm install --location=global npm
如果您不想全局安装 npm,请省略 --location=global
标志。在这种情况下,您需要调整所有后续的 npm
命令以使用安装在 bokehjs/node_modules
下的本地版本。
接下来,仍在 bokehjs
子目录中,运行以下命令以安装 BokehJS 的所有 JavaScript 依赖项
npm ci
此命令将必要的软件包安装到 node_modules
子目录中。
注意
通常,您只需要在首次设置本地环境时执行一次此操作。但是,如果添加或更改了依赖项,则需要重复这些步骤以安装和更新相应的软件包。
5. 设置 pre-commit#
Bokeh 使用 pre-commit 来帮助您避免提交中的一些常见错误。
要在本地设置 pre-commit,请从源检出目录的顶层运行以下命令
python scripts/hooks/install.py
这将配置 pre-commit 以使用两个 Git 钩子,这些钩子将在您将提交推送到 Bokeh 的 GitHub 存储库时检查您的代码
- 代码库测试
git-commit 将运行 Bokeh 的 代码库测试 以检查代码库质量问题,例如空格和导入。这包括使用 Ruff、ESLint 和 isort 进行测试。
- 受保护的分支
git-commit 将确保您不会意外地将提交推送到 Bokeh 的受保护分支
main
和branch-x.y
上。
注意
根据您的系统,运行这些测试可能需要几十秒。如果任何测试失败,请检查控制台的输出。在大多数情况下,您将在其中找到有关需要更改哪些内容才能通过测试的必要信息。
要卸载 Git 钩子,请从源检出目录的顶层运行以下命令
python scripts/hooks/uninstall.py
6. 在本地构建和安装#
一旦您安装了所有必需的依赖项,构建和安装 Bokeh 和 BokehJS 的最简单方法是使用 pip。pip
是 Python 的包安装程序,在您 设置 conda 环境 时会自动安装。在运行 pip
之前,请确保您已激活了 bkdev
环境。
有两种方法可以使用 pip
安装 Bokeh 的本地开发版本
pip install -e .
Bokeh 将被安装以引用您的本地源目录。您对 Python 源代码所做的任何更改都将立即生效,无需任何其他步骤。这是在处理 Bokeh 代码库时推荐的模式。
pip install .
Bokeh 将安装到您的本地 Python
site-packages
目录中。在此模式下,对 Python 源代码的任何更改都不会生效,除非您再次运行pip install .
。
运行这两个命令中的任何一个也会构建并安装 BokehJS 的本地版本。如果您想跳过构建 BokehJS 的新版本并改用其他本地版本,请设置 BOKEHJS_ACTION
环境变量:BOKEHJS_ACTION="install" pip install -e .
注意
您需要在 BokehJS 源代码发生变化时每次重新构建 BokehJS。这可能是因为您自己进行了更改,或者因为您从 GitHub 拉取了更新的代码。重新运行 pip install -e .
以构建和安装 BokehJS。
偶尔,JavaScript 依赖项列表也会发生变化。如果发生这种情况,您需要在重新构建 BokehJS 之前重新运行上面 4. 安装 Node 包 部分中的说明。
7. 设置环境变量#
Bokeh 使用 环境变量 来控制库的不同部分如何操作和交互的几个方面。
要了解 Bokeh 中可用的所有环境变量,请参阅参考指南中的 bokeh.settings。
BOKEH_RESOURCES
#
在处理 Bokeh 的代码库时,需要注意的最重要的环境变量是 BOKEH_RESOURCES
。此变量控制要使用的 BokehJS 版本。
默认情况下,Bokeh 会从内容分发网络 (CDN) 下载 BokehJS 所需的任何 JavaScript 代码。如果您修改了任何 BokehJS 代码并在本地构建了 BokehJS,则需要更改 Bokeh 加载这些 JavaScript 资源的方式。除非您将 Bokeh 配置为使用您本地版本的 BokehJS 而不是 CDN 中的默认版本,否则您将看不到对 BokehJS 的本地更改的任何效果。
请注意,仅在运行示例时才应设置 BOKEH_RESOURCES
。当您运行测试或构建文档时,不应设置此变量(如果已设置,则取消设置),否则可能会出现错误。
您可以使用以下三种选项来使用您本地的 BokehJS 版本
- 使用
absolute-dev
将
BOKEH_RESOURCES
设置为absolute-dev
以从本地安装的 Bokeh 库的静态目录加载 JavaScript 资源。这样,Bokeh 还会使用未压缩的 BokehJS 资源以提高可读性。export BOKEH_RESOURCES=absolute-dev
$Env:BOKEH_RESOURCES = "absolute-dev"
set BOKEH_RESOURCES=absolute-dev
- 使用
inline
将
BOKEH_RESOURCES
设置为inline
以将所有必要的本地 JavaScript 资源直接包含在生成的 HTML 文件中。export BOKEH_RESOURCES=inline
$Env:BOKEH_RESOURCES = "inline"
set BOKEH_RESOURCES=inline
- 使用
server-dev
将
BOKEH_RESOURCES
设置为server-dev
以通过 Bokeh 服务器加载您的本地 BokehJS。首先,启动本地服务器。
BOKEH_DEV=true bokeh static
$Env:BOKEH_DEV = "true" bokeh.exe static
set BOKEH_DEV=true bokeh static
接下来,打开一个新的终端窗口并将
BOKEH_RESOURCES
设置为server-dev
。export BOKEH_RESOURCES=server-dev
$Env:BOKEH_RESOURCES = "server-dev"
set BOKEH_RESOURCES=server-dev
这样,您就可以访问更多开发功能,例如 源映射 以帮助调试原始 TypeScript 而不是编译后的 JavaScript。
有关更多详细信息,请参阅 Resources
。
BOKEH_DEV
#
在处理 Bokeh 的代码库时,还有其他一些有用的环境变量。本地开发最常见的设置都组合在变量 BOKEH_DEV
中。
要启用开发设置,请将 BOKEH_DEV
设置为 true
export BOKEH_DEV=true
$Env:BOKEH_DEV = "true"
set BOKEH_DEV=true
将 BOKEH_DEV
设置为 true
意味着以下设置
BOKEH_BROWSER=none
BOKEH_LOG_LEVEL=debug
BOKEH_MINIFIED=false
BOKEH_PRETTY=true
BOKEH_PY_LOG_LEVEL=debug
BOKEH_RESOURCES=server
但并不完全等同于分别设置这些变量。
这样,Bokeh 将使用本地和未压缩的 BokehJS 资源,默认日志级别会提高,生成的 HTML 和 JSON 代码将更易于人类阅读,并且 Bokeh 不会在每次调用 show()
时打开一个新的浏览器窗口。
注意
设置 BOKEH_DEV=true
会启用 BOKEH_RESOURCES=server
,这需要一个资源服务器。如果需要,用户可以通过分别运行 BOKEH_DEV=true bokeh static
(在 Linux 上)命令(例如,在另一个终端或控制台中)来提供此类服务器。
尽管将服务器资源用于开发是最稳健的方法,但用户可以通过将 BOKEH_RESOURCES
设置为 inline
来稍微简化其设置。
8. 测试您的本地设置#
运行以下测试以检查所有内容是否已正确安装和设置
测试 Bokeh 核心#
首先,使用以下命令测试 Bokeh 安装
python -m bokeh info
您应该看到类似于以下内容的输出
Python version : 3.12.3 | packaged by conda-forge | (main, Apr 15 2024, 18:38:13) [GCC 12.3.0]
IPython version : 8.19.0
Tornado version : 6.3.3
NumPy version : 2.0.0
Bokeh version : 3.5.1
BokehJS static path : /opt/anaconda/envs/test/lib/python3.12/site-packages/bokeh/server/static
node.js version : v20.12.2
npm version : 10.8.2
jupyter_bokeh version : (not installed)
Operating system : Linux-5.15.0-86-generic-x86_64-with-glibc2.35
运行示例#
接下来,运行 Bokeh 附带的一些独立示例。
确保 环境变量 BOKEH_RESOURCES
设置为 absolute-dev
或 inline
以使用您本地的 BokehJS 版本。在源代码检出目录中,运行以下命令
BOKEH_RESOURCES=inline python examples/basic/data/transform_markers.py
$Env:BOKEH_RESOURCES = "inline"
python.exe .\examples\basic\data\transform_markers.py
set BOKEH_RESOURCES=inline
python examples\basic\data\transform_markers.py
这会在本地创建一个名为 transform_markers.html
的文件。当您在 Web 浏览器中打开此文件时,它应该会显示此可视化效果
运行 Bokeh 服务器#
使用 Bokeh 的另一种方法是作为 服务器。设置 环境变量 BOKEH_DEV=false
并运行源代码检出目录中的 bokeh serve
命令
BOKEH_DEV=false python -m bokeh serve --show examples/server/app/sliders.py
$Env:BOKEH_DEV = "False"
python.exe -m bokeh serve --show .\examples\server\app\sliders.py
set BOKEH_DEV=false
python -m bokeh serve --show examples\server\app\sliders.py
这应该会打开一个带有交互式图形的浏览器
所有滑块都允许对正弦波进行交互式控制,每次更新都会使用新参数重新绘制线条。--show
选项会打开一个 Web 浏览器。Bokeh 服务器的默认 URL 为 localhost:5006
。
故障排除#
更新现有的开发环境并不总是按预期工作。作为一般规则,请确保您的 conda 环境、Node 包 和 本地构建 始终是最新的。
以下列表包含在设置开发环境时可能遇到的常见问题的解决方案
缺少 Git 标签(KeyError: '0.0.1'
)
有时,如果 Bokeh 存储库的标签尚未克隆到您的本地目录,您可能会遇到问题。例如,您可能会在控制台输出中看到 KeyError: '0.0.1'
。
要检查是否存在必要的标签,请运行以下命令
git tag -l | tail
git tag -l
git tag -l
如果不存在任何标签,请确保您按照 将 Bokeh 存储库设置为其他上游 的步骤操作。
由于行尾导致 Git 提交失败(test_code_quality.py
,File contains carriage returns
)
在 Windows 系统上,尝试将本地分支推送到 GitHub 上的远程分支时,可能会遇到 File contains carriage returns at end of line: <file path>
错误。这是因为 Bokeh 仅允许 LF 行结束符,而某些基于 Windows 的工具可能会添加 CR LF 行结束符。
如果遇到此错误,请尝试运行以下命令:git config --global core.autocrlf false
。运行此命令后,删除并重新克隆您的分叉存储库(请参阅 2. Fork 和克隆存储库)。
从旧版本更新后的错误
如果在更新旧环境后仍然遇到错误,请使用 conda remove --name bkdev --all
,删除本地 bokeh
文件夹,并按照本指南中的步骤重新安装开发环境,从 开始。
克隆时网络连接缓慢
如果您在尝试克隆我们的存储库时遇到网络连接缓慢或超时问题,请考虑执行 **浅克隆**。此方法下载较少的提交,从而加快克隆过程并减少数据传输量。
对于带宽有限或克隆速度缓慢的贡献者来说,使用浅克隆可能是一种有效的解决方法。但是,请注意其局限性,并了解如何在必要时将其转换回完整克隆。
要创建存储库的浅克隆,请运行
git clone --depth <number-of-commits> [email protected]:bokeh/bokeh.git
git clone --depth <number-of-commits> https://github.com/bokeh/bokeh.git
将 <number-of-commits>
替换为您希望克隆的提交次数。
例如,仅克隆最新的提交
git clone --depth 1 [email protected]:bokeh/bokeh.git
git clone --depth 1 https://github.com/bokeh/bokeh.git
如果您只对特定分支的历史记录感兴趣,可以将 –single-branch 选项与 –depth 结合使用,以进一步将克隆限制到单个分支。运行
git clone --depth 1 --branch <branch-name> --single-branch [email protected]:bokeh/bokeh.git
git clone --depth 1 --branch <branch-name> --single-branch https://github.com/bokeh/bokeh.git
浅克隆的局限性
虽然浅克隆非常有用,但它也有一些局限性
**有限的 Git 操作:**需要完整历史记录的操作(例如,某些合并策略、生成综合日志)将不可行。
**分支限制:**如果您未克隆所有分支(–single-branch 选项),则可能无法在分支之间切换,除非执行其他步骤。
**不准确的版本信息:**当存储库被浅克隆时,通过 bokeh.__version__ 获取的版本信息可能会显示不正确的数据,例如“dev”标签。
将浅克隆转换为完整克隆
如果您发现需要访问存储库的完整历史记录以执行更复杂的任务,可以通过获取剩余的历史记录将浅克隆转换为完整克隆
要将克隆加深特定数量的提交
git fetch --deepen=<additional-commits>
要将浅克隆完全转换为完整克隆(获取所有历史记录)
git fetch --unshallow
此命令将下载存储库其余的历史记录,将您的浅克隆转换为常规的完整克隆。
有关运行和安装 Bokeh 的更多信息,请查看 贡献者可用的其他资源。如有任何疑问,请随时在 Bokeh 论坛 或 Bokeh 贡献者 Slack 中提问。