本文对 Jupyter 的二次开发方式进行总结梳理,主要包括 Jupyter Lab 前端、Jupyter Server 后端、Jupyter Hub 部署工具和 IPykernel 等组件。

Jupyter Lab

JupyterLab 是一个灵活而强大的前端接口,提供了多种方式进行二次开发和扩展,以满足不同的需求和使用场景。以下是关于 JupyterLab 前端二次开发的主要方式的总结:

扩展开发

JupyterLab 的扩展开发是其二次开发的核心方式之一,允许开发者通过插件架构扩展或定制 JupyterLab 的功能。扩展是独立的模块,能够添加新功能、修改现有功能,甚至是集成外部工具和服务。开发者可以利用 JupyterLab 的插件系统,在不影响核心代码的情况下,创建和分发功能强大的扩展,这些扩展可以从简单的 UI 增强到复杂的集成解决方案。

开发 JupyterLab 插件通常使用 Node.js、TypeScript 和 React.js 技术栈。官方提供了详细的 开发者指南,帮助开发者快速上手。常见的插件类型包括 UI 增强插件(如添加工具栏按钮或菜单项)、数据集成插件(如连接数据库或云存储服务)、自定义渲染插件(为特定数据类型提供特殊的显示方式)和交互组件插件(如创建新的表单、图表或编辑器)。这些插件可以通过 JupyterLab 的扩展管理器进行安装和管理,极大地提升了 JupyterLab 的灵活性和可扩展性。

自定义界面

JupyterLab 的用户界面可以通过多种方式进行自定义,从简单的样式调整到全面的主题开发。开发者可以使用 CSS 或 SCSS 文件修改 JupyterLab 的外观,覆盖默认样式或为特定组件定义新的样式规则。这种方式适合需要微调 JupyterLab 界面或调整其视觉风格的需求,例如更改配色方案、调整组件的间距或字体样式。

此外,开发者还可以创建主题插件,允许用户在 JupyterLab 中轻松切换不同的 UI 主题。这种插件通常包含全局样式文件,以及可能的 JavaScript 逻辑,用于动态调整界面元素的外观。对于更高级的定制,JupyterLab 还支持预配置工作空间布局和面板设置,开发者可以通过修改配置文件或编写插件,定制默认的工作空间布局,让用户每次启动时都能看到特定的界面配置。

前端 API 扩展

JupyterLab 提供了丰富的前端 API,允许开发者与核心功能进行深度交互,从而实现扩展和定制。通过这些 API,开发者可以在不修改 JupyterLab 核心代码的情况下,扩展现有组件的功能,或者添加新的交互逻辑。这些扩展点覆盖了文件操作、会话管理、内核交互、命令系统和数据可视化等多个方面,使得 JupyterLab 成为一个高度可定制的平台。

开发者可以利用这些 API 在命令面板中添加自定义命令,在文件浏览器中添加新的操作按钮,或者创建新的交互式组件和面板。这些扩展不仅能为用户提供更丰富的功能,还能提高工作效率。例如,开发者可以创建一个自定义命令,将特定的工作流自动化,或者通过前端 API 扩展数据处理功能,使得 JupyterLab 能够支持更多的数据格式或处理方式。

集成第三方服务

通过与第三方服务的集成,JupyterLab 可以实现更广泛的功能和更强的互操作性。开发者可以使用 JupyterLab 的前端与外部 API 或 Webhook 集成,实现数据交换、触发外部服务,或获取实时数据更新。这种方式非常适合需要与云存储服务、数据库、版本控制系统(如 Git)或其他外部工具集成的场景。

此外,JupyterLab 还可以通过插件或自定义扩展,将第三方可视化工具(如 Plotly、D3.js、Bokeh 等)与平台紧密结合,增强数据分析和展示的能力。开发者可以编写插件,将这些工具集成到 JupyterLab 的界面中,提供丰富的图表和可视化效果,从而为用户带来更强大的数据处理和分析体验。

这里是一个与 Git 相关的第三方服务插件实现。

小工具与交互组件

JupyterLab 允许开发者创建自定义的小工具(Widgets)和交互组件,以增强用户的交互体验。这些组件可以嵌入到 Notebook 中,让用户通过交互的方式与代码的输入输出进行沟通。开发者可以使用 ipywidgets 库创建并发布这些 Widgets,实现如滑块、按钮、图表等交互元素,使得数据分析和展示更加直观和动态。

此外,开发者还可以构建自定义的仪表板和面板,用于展示数据分析结果、监控数据流、或提供实时的计算反馈。这些面板可以被嵌入到 JupyterLab 的侧边栏或主区域,作为工作空间的一部分,为用户提供更丰富和专业的工作环境。这种方式特别适合需要实时数据监控或动态可视化的应用场景。

这里 是官方的文档,可以参考进行开发实现。

Jupyter Server

Jupyter Server 是 JupyterLab 的后端部分,负责管理内核、处理请求、提供 API,以及与前端进行通信。对 Jupyter Server 进行二次开发,可以为 JupyterLab 提供更强大的功能、集成能力和扩展性。以下是 Jupyter Server 二次开发的主要方式及其详细描述:

扩展开发

Jupyter Server 扩展(Extensions)是最常见的二次开发方式,允许开发者在不修改核心代码的情况下添加或修改服务器功能。通过编写自定义扩展,开发者可以增加新的 API 路由、处理特定类型的请求、以及在特定事件发生时触发自定义操作。

这些扩展通常采用 Python 编写,并利用 Tornado 框架来管理 HTTP 请求。开发者可以通过创建新的 Tornado Request Handlers 来处理自定义的 API 路由。例如,开发者可以编写一个扩展,用于处理特定文件类型的上传和转换,或者创建一个 API 用于与外部系统的集成。这些扩展可以通过配置文件启用或禁用,使得 Jupyter Server 的功能更加灵活和模块化。

参考官方示例:https://github.com/jupyter-server/jupyter_server/tree/main/examples/simple

参考官方文档:https://jupyter-server.readthedocs.io/en/latest/developers/index.html

身份验证与安全扩展

身份验证和安全性是 Jupyter Server 二次开发的重要领域。默认情况下,Jupyter Server 提供了几种基本的身份验证机制,如密码登录和令牌认证。为了满足更高的安全需求,开发者可以扩展或替换默认的身份验证机制,集成自定义的认证系统,例如 OAuth、LDAP、JWT(JSON Web Tokens)等。

通过编写自定义认证扩展,开发者可以控制用户访问权限,并根据用户角色或权限级别限制对某些功能或数据的访问。例如,可以开发一个扩展,使得只有特定用户组才能启动某些高资源消耗的内核,或访问特定的数据库。除此之外,开发者还可以实现双因素认证、IP 限制、HTTPS 加密等安全措施,确保 Jupyter Server 在企业级或高安全性场景中的使用安全可靠。

参考官方示例:https://github.com/jupyter-server/jupyter_server/tree/main/examples/authorization

内核管理与扩展

Jupyter Server 的一个核心功能是管理内核(Kernel),负责启动、停止和监控计算内核。开发者可以通过扩展内核管理功能,增加对新编程语言或计算框架的支持。例如,可以为特定的科学计算语言创建新的内核,使其能够在 JupyterLab 中被使用。

扩展内核管理不仅仅是增加对新语言的支持,开发者还可以自定义内核的启动参数、资源分配策略、日志管理等。例如,可以开发一个扩展,使得某些内核能够动态分配更多的计算资源,或者在内核启动时自动加载特定的库和环境变量。通过扩展内核管理功能,Jupyter Server 可以被定制为支持各种复杂的计算任务和多样化的编程环境。

参考官方文档:https://jupyter-kernel-mgmt.readthedocs.io/en/latest/

定制 API 和服务

Jupyter Server 提供了一系列 API,用于与前端进行交互,并管理用户会话、文件操作、内核通信等。开发者可以通过扩展或定制这些 API,实现更复杂的功能和服务。例如,可以开发自定义的 API,用于处理用户身份验证、访问控制、数据处理任务,甚至与外部系统的集成。

开发者可以通过继承和扩展现有的 Tornado 请求处理类(Request Handlers),来创建新的 API 路由和处理逻辑。这种方式允许开发者为 Jupyter Server 增加新的服务端功能,例如为团队协作开发共享的工作空间管理 API,或者为数据科学团队开发自动化数据清洗和预处理服务。通过定制 API 和服务,Jupyter Server 可以被扩展为一个功能强大、灵活的后端服务器,支持多种复杂的工作流和业务需求。

参考官方文档:https://jupyter-server.readthedocs.io/en/latest/developers/rest-api.html

文件系统与存储扩展

Jupyter Server 默认支持本地文件系统作为数据存储,但在某些情况下,开发者可能需要集成其他类型的存储系统,如云存储、分布式文件系统、数据库等。通过扩展文件系统管理功能,开发者可以定制 Jupyter Server 的文件读写操作,使其能够支持多种存储方案。

例如,开发者可以编写扩展,使得 Jupyter Server 可以直接访问和操作 Amazon S3、Google Cloud Storage、HDFS 等云存储服务。也可以开发一个插件,使得服务器能够与数据库系统(如 MongoDB、PostgreSQL)无缝集成,实现文件的存储和检索。这些扩展不仅提升了 Jupyter Server 的灵活性,还使得其能够更好地适应企业级数据管理和存储需求。

参考官方文档:

https://jupyter-server.readthedocs.io/en/latest/developers/savehooks.html

https://jupyter-server.readthedocs.io/en/latest/developers/contents.html

Jupyter Hub

JupyterHub 是一个多用户的 Jupyter Notebook 服务器,允许多个用户通过浏览器访问和运行 Jupyter Notebook 实例,可以将其视为一种部署工具。JupyterHub 提供了多种二次开发和扩展方式,以下是主要方式及其详细描述:

自定义身份验证器(Authenticator)

JupyterHub 支持自定义身份验证器(Authenticator),用于管理用户的身份验证方式。默认情况下,JupyterHub 提供了几种常见的身份验证器,例如基于本地系统用户的 PAMAuthenticator、使用 OAuth2 的 GitHubAuthenticator 等。但是,为了满足特殊的安全需求或集成企业内部的认证系统,开发者可以编写自定义的身份验证器。

通过扩展或替换默认的身份验证器,开发者可以集成 LDAP、OAuth、SAML、JWT 等多种身份验证方式。例如,开发者可以创建一个自定义的 OAuth2 身份验证器,使得用户可以使用企业的单点登录系统(SSO)登录 JupyterHub。这些自定义身份验证器通常通过继承 JupyterHub 的 Authenticator 基类来实现,并重写相应的方法以处理登录请求、用户信息验证和用户管理。

参考官方文档:https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html

参考示例:https://github.com/sparkingarthur/jupyterhub-localsqliteauthenticator

自定义 Spawner

Spawner 是 JupyterHub 中用于启动用户 Notebook 实例的组件。默认的 Spawner 使用本地进程启动 Notebook 实例,但开发者可以通过编写自定义的 Spawner 来使用不同的资源管理器或容器化技术来启动实例。例如,DockerSpawner 可以用于在 Docker 容器中启动 Notebook 实例,而 KubeSpawner 则用于在 Kubernetes 集群中启动实例。

自定义 Spawner 可以实现多种场景下的资源管理和隔离。例如,开发者可以编写一个 Spawner,使其能够根据用户角色或需求动态分配计算资源,或者使用远程计算节点启动 Notebook 实例。通过自定义 Spawner,JupyterHub 可以与不同的基础设施集成,从而在云环境、容器环境或高性能计算集群中部署 JupyterHub 服务。

参考官方示例:https://github.com/jupyterhub/dockerspawner/tree/main/examples/simple

集成第三方服务与扩展 API

JupyterHub 可以通过定制和扩展其 API,与第三方服务进行深度集成。开发者可以创建自定义的 API 路由,用于实现特定的功能或与外部系统交互。例如,开发者可以集成 GitHub、GitLab 等版本控制系统,使用户能够直接从 JupyterHub 中管理代码仓库,或集成 Slack、Teams 等消息通知服务,为用户提供实时的任务提醒和协作支持。

通过扩展 API,JupyterHub 可以被用作集成多种工具和服务的中心节点。开发者可以为 JupyterHub 添加新的 RESTful API 端点,供前端或外部应用调用,来管理用户、控制资源、或者触发自动化工作流。例如,一个自定义 API 可以允许管理员批量创建用户、分配资源、或调度批处理任务。此外,开发者还可以利用 Webhooks 来实时接收和处理外部事件,使得 JupyterHub 成为更加智能和自动化的工作平台。

参考官方文档:https://jupyterhub.readthedocs.io/en/stable/reference/rest-api.html

IPykernel

IPython Kernel(简称 IPykernel)是 Jupyter Notebook 的一个核心组件,负责执行用户的代码并将结果返回到前端。IPykernel 支持 Python 代码的执行,并处理与 Jupyter 前端的交互。通过对 IPykernel 进行二次开发,开发者可以定制其行为、扩展功能或集成新的计算环境。以下是 IPykernel 二次开发的主要方式及其详细描述:

扩展 Magic 命令

IPython 提供了丰富的魔法命令(Magic Commands),用于简化和增强 Notebook 的使用体验。这些命令可以直接在代码单元格中调用,以便执行特定的任务,如文件操作、时间测量、环境管理等。通过扩展魔法命令,开发者可以为用户提供更多便捷的操作接口和自动化工具。

开发者可以创建自定义的魔法命令,处理特定的计算任务或集成外部工具。例如,可以编写一个魔法命令,用于自动化数据清洗、文件上传下载、调用外部 API 等。自定义魔法命令通常通过继承 IPython 的 Magics 类,并在其中定义新的命令方法。魔法命令的扩展使得用户能够通过简洁的命令行接口,执行复杂的操作和工作流,极大地提升了 Jupyter Notebook 的使用效率和灵活性。

参考官方文档:https://ipython.readthedocs.io/en/stable/config/custommagics.html

参考示例:https://github.com/catherinedevlin/ipython-sql

自定义内核

IPykernel 的核心功能是执行 Python 代码,但开发者可以通过创建自定义内核,扩展其支持的编程语言或计算环境。例如,可以创建一个内核,使其支持执行特定领域的编程语言(如 Julia、R、Scala),或集成特定的计算引擎(如 TensorFlow、PyTorch、Apache Spark)。

自定义内核通常涉及到编写一个新的内核启动器,处理内核与 Jupyter 前端的通信协议,并管理代码的执行过程。开发者可以通过继承 IPykernel 的基类 Kernel,并重写其中的方法来实现特定的行为。例如,可以编写一个内核,使其在执行代码之前先进行代码预处理,或者在执行后自动将结果存储到外部数据库中。这种方式使得 Jupyter 可以扩展为支持多种编程语言和计算框架的平台,适应各种复杂的开发和研究场景。

参考示例:https://github.com/Hourout/mysql_kernel