设置开发环境#

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 为您创建和管理虚拟环境。因此,您不需要 venvvirtualenvpipenv 等工具。虽然从技术上讲,可以在没有 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 存储库中的环境文件更新或您切换分支以处理不同的问题时,可能会发生这种情况。

要了解有关创建和管理 conda 环境的更多信息,请参阅 Conda 文档 中的 管理环境

4. 安装 Node 包#

构建 BokehJS 还需要使用 Node 包管理器 (npm) 安装 JavaScript 依赖项。如果您已遵循 上述说明conda 已将必要的 npmnode.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 的 代码库测试 以检查代码库质量问题,例如空格和导入。这包括使用 RuffESLintisort 进行测试。

受保护的分支

git-commit 将确保您不会意外地将提交推送到 Bokeh 的受保护分支 mainbranch-x.y 上。

注意

根据您的系统,运行这些测试可能需要几十秒。如果任何测试失败,请检查控制台的输出。在大多数情况下,您将在其中找到有关需要更改哪些内容才能通过测试的必要信息。

要卸载 Git 钩子,请从源检出目录的顶层运行以下命令

python scripts/hooks/uninstall.py

6. 在本地构建和安装#

一旦您安装了所有必需的依赖项,构建和安装 Bokeh 和 BokehJS 的最简单方法是使用 pippip 是 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-devinline 以使用您本地的 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 浏览器中打开此文件时,它应该会显示此可视化效果

../../_images/bokeh_transform_markers_html.png

运行 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

这应该会打开一个带有交互式图形的浏览器

../../_images/bokeh_app_sliders.png

所有滑块都允许对正弦波进行交互式控制,每次更新都会使用新参数重新绘制线条。--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.pyFile 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 和克隆存储库)。

此命令配置 git 始终保留原始的仅 LF 换行符。有关其他选项,请参阅 GitHub 文档Git 配置文档

从旧版本更新后的错误

如果在更新旧环境后仍然遇到错误,请使用 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 中提问。