设置开发环境#

Bokeh项目由两个主要组件组成:用Python编写的Bokeh包源代码,以及用TypeScript编写的BokehJS客户端库。

因此,您需要设置两个环境来为Bokeh做出贡献:一个Python环境和一个TypeScript环境。本章将引导您完成设置完整开发环境的所有必要步骤。

1. 检查基本要求#

安装或更新Git#

Bokeh 的源代码存储在 Git 源代码控制仓库中。开始使用 Bokeh 的第一步是在您的系统上安装或更新 Git。

根据您使用的是Windows、OSX还是Linux,有不同的方法可以做到这一点。要在任何平台上安装Git,请参考安装Git部分的Pro Git Book

如果您从未使用过 Git,您可以在 Git 文档 中找到多个初学者教程和资源的链接。

安装或更新 conda#

在Bokeh代码库上工作需要安装几个不是Python包的软件包。例如,用于TypeScript开发的Node.js或用于测试和导出的Selenium

为了能够在一个地方管理Python和非Python依赖项,Bokeh使用了conda包管理器conda是免费的Anaconda Python发行版的一部分,适用于Windows、macOS和Linux。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 分支”)。有关创建分支的更多信息,请参阅Fork a repoGitHub 帮助中。

接下来,将您想要使用的Bokeh仓库版本克隆到硬盘上的本地文件夹中。使用git clone或按照克隆分叉仓库的说明在GitHub帮助中操作。

克隆仓库会在您的文件系统位置创建一个bokeh目录。这个本地的bokeh目录在本文档的其余部分被称为源代码检出

在继续之前,有必要使用以下命令将Bokeh仓库添加为额外的上游:

git remote add upstream git@github.com: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来设置环境并安装所有必要的包。“test”环境文件按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/ file>。每当测试环境中的依赖项发生变化时,更新您的本地环境是必要的。这可能在主Bokeh存储库中的环境文件更新时发生,或者当您切换分支以处理不同问题时发生,例如。

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

4. 安装Node包#

构建 BokehJS 还需要使用 Node Package Manager (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. 设置预提交#

Bokeh 使用 pre-commit 来帮助你在提交时防止一些常见的错误。

要在本地设置预提交,请从您的源代码检出目录的顶层运行以下命令:

python scripts/hooks/install.py

这将配置 pre-commit 使用两个 Git 钩子,每当您向 Bokeh 的 GitHub 仓库推送提交时,这些钩子将检查您的代码:

Codebase tests

git-commit 将运行 Bokeh 的 代码库测试 来检查 代码库质量问题,例如空格和导入。这包括 使用 RuffESLintisort 进行测试。

Protected branches

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

注意

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

要卸载 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:

Use 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
Use inline

BOKEH_RESOURCES 设置为 inline 以直接在生成的 HTML 文件中包含所有必要的本地 JavaScript 资源。

export BOKEH_RESOURCES=inline
$Env:BOKEH_RESOURCES = "inline"
set BOKEH_RESOURCES=inline
Use 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

这样,您可以访问更多的开发功能,例如 source maps 来帮助调试原始的 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 代码将更易于人类阅读,并且每次调用 show() 时,Bokeh 不会打开新的浏览器窗口。

注意

设置 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。当你在网页浏览器中打开这个文件时,它应该显示以下可视化内容:

../../_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 选项会打开一个网页浏览器。Bokeh 服务器的默认 URL 是 localhost:5006

故障排除#

更新现有的开发环境并不总是如预期那样工作。作为一般规则,请确保您的 conda 环境, Node 包, 和 本地构建 始终保持最新。

以下列表包含在设置开发环境时可能遇到的常见问题的解决方案:

Git tags missing (KeyError: '0.0.1')

有时,如果Bokeh仓库的标签没有被克隆到本地目录,您可能会遇到问题。例如,您可能会在控制台输出中看到KeyError: '0.0.1'

要检查必要的标签是否存在,请运行以下命令:

git tag -l | tail
git tag -l
git tag -l

如果没有标签存在,请确保您按照以下步骤操作 将Bokeh仓库设置为额外的上游

Git commit fails due to line endings (test_code_quality.py, File contains carriage returns)

在Windows系统上,当您尝试将本地分支推送到GitHub上的远程分支时,可能会遇到File contains carriage returns at end of line: path>错误。这是因为Bokeh只允许LF行尾,而一些基于Windows的工具可能会添加CR LF行尾。

如果你看到这个错误,尝试运行以下命令: git config --global core.autocrlf false。运行此命令后,删除并 重新克隆你的分叉仓库(参见 2. 分叉并克隆仓库

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

Errors after updating from an older version

如果在更新旧环境后仍然遇到错误,请使用 conda remove --name bkdev --all,删除本地的 bokeh 文件夹, 并按照本指南中的步骤从头开始重新安装开发环境 the beginning

Slow network connections when cloning

如果您在尝试克隆我们的仓库时遇到网络连接缓慢或超时问题,请考虑执行浅克隆。这种方法下载的提交较少,从而加快了克隆过程并减少了数据传输量。

使用浅克隆可以成为带宽有限或克隆速度较慢的贡献者的有效解决方案。然而,请注意其局限性,并知道如何在必要时将其转换回完整克隆。

要创建存储库的浅克隆,请运行:

git clone --depth <number-of-commits> git@github.com:bokeh/bokeh.git
git clone --depth <number-of-commits> https://github.com/bokeh/bokeh.git

替换为您希望克隆的提交次数。

例如,仅克隆最新的提交:

git clone --depth 1 git@github.com: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 git@github.com: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 DiscourseBokeh的贡献者Slack上提问。