Notebook 7 服务端扩展:基于 Jupyter Server 的迁移、复用与开发指南
【免费下载链接】notebookJupyter Interactive Notebook项目地址: https://gitcode.com/GitHub_Trending/no/notebook
Notebook 7 的底层服务端已从经典的 Notebook Server 迁移至 Jupyter Server,这意味着它可以像 JupyterLab、NBClassic 一样作为 Jupyter Server 上的一个扩展运行,并直接复用 Jupyter 生态中已有的海量服务端扩展。本文基于当前仓库的官方迁移文档与源码实现,系统讲解从 Notebook Server 到 Jupyter Server 的迁移要点、服务端扩展的复用方式与开发路径,并给出可落地的配置示例与源码级佐证,帮助你在 Notebook 7 上平滑迁移、开箱即用既有扩展,或编写属于自己的服务端扩展。
Notebook 7 与 Jupyter Server:架构背景
在 Notebook 7 之前,经典 Notebook 由notebook包自带的 Notebook Server(基于 Tornado 的独立服务器)提供服务。而 Notebook 7 的诞生彻底改变了这一架构:Notebook 7 现在基于 Jupyter Server——一个全新的服务器应用,它允许在同一个服务器进程上同时运行多个 Jupyter 应用(例如 Notebook、JupyterLab、NBClassic 等)。
这一架构选择的直接收益是扩展生态的复用:由于 Notebook 7 与 JupyterLab、NBClassic 共享同一套 Jupyter Server 基础设施,Jupyter 生态中大量已存在的服务端扩展(例如 jupyter-server-proxy、jupyter-resource-usage、nbgitpuller 等)可以原封不动(as is)地直接复用,无需为 Notebook 7 做任何专门适配。
从源码可以确认这一架构事实:
- notebook/app.py 中
JupyterNotebookApp直接继承自LabServerApp(jupyterlab_server包),并通过NotebookConfigShimMixin(来自notebook_shim)兼容经典 Notebook 的命令行配置,例如:
class JupyterNotebookApp(NotebookConfigShimMixin, LabServerApp): """The notebook server extension app.""" name = "notebook" app_name = "Jupyter Notebook" ... load_other_extensions = True- notebook/init.py 显式声明了 Jupyter Server 扩展入口点:
def _jupyter_server_extension_paths() -> list[dict[str, str]]: return [{"module": "notebook"}] def _jupyter_server_extension_points() -> list[dict[str, Any]]: # Deferred import to avoid importing the app at package import time from .app import JupyterNotebookApp # noqa: PLC0415 return [{"module": "notebook", "app": JupyterNotebookApp}]- 在 jupyter-config/jupyter_server_config.d/notebook.json 中,notebook 包通过标准的
ServerApp.jpserver_extensions配置被声明为 Jupyter Server 的启用扩展:
{ "ServerApp": { "jpserver_extensions": { "notebook": true } } }- 在 pyproject.toml 中,notebook 将运行时依赖声明为
jupyter_server>=2.19.0,<3与notebook_shim>=0.2,<0.3,确保 Jupyter Server 与兼容层始终可用。
也就是说,Notebook 7 本身就“是一个”Jupyter Server 扩展,这既是它能够与 JupyterLab、NBClassic 共存于同一服务器的原因,也是它能够复用整个 Jupyter 服务端扩展生态的根本前提。
从 Notebook Server 迁移:你需要做什么
对于已经运行在经典 Notebook Server 上的用户与运维者,官方迁移指南明确给出了行动方向。
迁移的核心结论
Jupyter Server 官方文档提供了完整的从经典 Notebook Server 迁移到 Jupyter Server的指南(原文以外部链接给出,本仓库不复制其内容,但迁移要点可以概括为):
- 经典 Notebook Server 的配置项、命令行参数大多由
notebook_shim兼容层继续支持,已有的jupyter_notebook_config.py风格配置需要逐步迁移到 Jupyter Server 的配置体系(如jupyter_server_config.py); - 服务端由
jupyter notebook启动演变为基于 Jupyter Server 的统一服务器启动; - 原本为经典 Notebook Server 编写的服务端扩展需要评估其兼容性,多数基于 Jupyter Server 的扩展可直接复用。
多界面共存是迁移后的典型形态
迁移后最直观的变化是:同一台服务器上可以同时提供多个 Jupyter 前端界面。这一点在 docs/source/migrating/multiple-interfaces.md 中有完整说明:
- Notebook 7 + NBClassic + JupyterLab 并存时,三个前端分别通过
/tree(Notebook 7)、/nbclassic/tree(NBClassic)与/lab(JupyterLab)访问; - 经典 Notebook UI 如今以 NBClassic 这一 Jupyter Server 扩展的形式独立发布,可以
pip install nbclassic单独安装; - 也可以通过命令行在普通 Jupyter Server 上手动启用:
> jupyter server --ServerApp.jpserver_extensions="nbclassic=True"这条命令会以/tree路径提供 NBClassic 前端。
此外,从 notebook/app.py 的initialize_handlers可以看到,Notebook 7 在启动时会检测nbclassic是否启用,并把结果写入page_config["nbclassic_enabled"],用于前端界面切换(Interface 下拉菜单):
nbclassic_enabled = self.server_extension_is_enabled("nbclassic") page_config["nbclassic_enabled"] = nbclassic_enabled对应的server_extension_is_enabled方法(notebook/app.py)直接查询 Jupyter Server 的extension_manager:
def server_extension_is_enabled(self, extension: str) -> bool: """Check if server extension is enabled.""" if self.serverapp is None: return False try: extension_enabled = ( self.serverapp.extension_manager.extensions[extension].enabled is True ) except (AttributeError, KeyError, TypeError): extension_enabled = False return extension_enabled这从源码层面印证了:Notebook 7 的前端行为(是否展示界面切换入口)是由 Jupyter Server 的扩展启用状态驱动的,服务端扩展体系已经深度融入 Notebook 7 的运行机制。
服务端扩展的复用:生态中的扩展可直接使用
由于 Notebook 7 与 JupyterLab 共享 Jupyter Server 底座,服务端扩展的复用遵循**“装即用”**原则:
- 通过
pip安装目标服务端扩展包; - 确认该扩展在 Jupyter Server 配置(
jpserver_extensions)中已启用(多数扩展安装时会自动注册配置片段); - 启动
jupyter notebook(即启动基于 Jupyter Server 的 Notebook 7),扩展即随服务器加载。
扩展的启用状态受 Jupyter Server 统一管理,用户可以通过以下命令查看已启用的扩展:
jupyter server extension list需要留意的是:虽然扩展可以“原封不动复用”,但前端扩展(Frontend Extensions)并不在此列。Notebook 7 的前端基于 JupyterLab,因此针对 Notebook < 7 或 NBClassic 开发的前端扩展无法直接兼容,这一点在 docs/source/migrating/frontend-extensions.md 中有明确警告。而服务端扩展由于运行在 Jupyter Server 层、与具体前端无关,因此具备天然的可复用性——这正是本文所聚焦的主题。
编写服务端扩展:官方开发路径与仓库实现参考
对于需要自行开发服务端扩展的开发者,Jupyter Server 官方文档提供了**编写服务端扩展(authoring server extensions)**的指南(原文以外部链接给出)。结合本仓库的实现,可以梳理出标准的开发路径与核心约定。
开发路径概览
一个 Jupyter Server 扩展通常由以下几部分组成:
- Python 模块:包含扩展的
load_jupyter_server_extension(serverapp)入口函数,或在模块中声明扩展应用类; - 扩展入口点声明:在包的
__init__.py中实现_jupyter_server_extension_paths()(声明模块)与/或_jupyter_server_extension_points()(声明应用类); - 启用配置:通过安装时的配置片段(如
jupyter_server_config.d目录下的 JSON 文件)或手动设置ServerApp.jpserver_extensions启用。
仓库源码中的实现范本
本仓库本身就是“编写 Jupyter Server 扩展”的最佳范本:
- 入口点声明见 notebook/init.py:
def _jupyter_server_extension_paths() -> list[dict[str, str]]: return [{"module": "notebook"}] def _jupyter_server_extension_points() -> list[dict[str, Any]]: from .app import JupyterNotebookApp return [{"module": "notebook", "app": JupyterNotebookApp}]其中_jupyter_server_extension_points通过延迟导入(deferred import)避免在包导入阶段就加载应用类,这是一种值得借鉴的性能实践。
扩展应用类见 notebook/app.py:
JupyterNotebookApp继承LabServerApp与NotebookConfigShimMixin,并:- 通过
@default装饰器声明静态资源目录(static_dir)、模板目录(templates_dir)等路径; - 通过
initialize_handlers()注册TreeHandler、NotebookHandler、FileHandler、ConsoleHandler、TerminalHandler、CustomCssHandler等页面处理器; - 通过
flags扩展命令行开关(如--expose-app-in-browser、--custom-css)。
- 通过
启用配置见 jupyter-config/jupyter_server_config.d/notebook.json,该文件在安装时被放置到 Jupyter 的
jupyter_server_config.d目录(对应 pyproject.toml 中的"jupyter-config/jupyter_server_config.d" = "etc/jupyter/jupyter_server_config.d"数据文件映射),从而实现开箱即用。
测试侧的验证方式
仓库的测试基础设施也展示了如何在测试环境中装配一个 Jupyter Server 扩展应用:tests/conftest.py 中通过_link_jupyter_server_extension(jp_serverapp)把扩展应用链接到jp_serverapp后再执行initialize():
@pytest.fixture def notebookapp(jp_serverapp, make_notebook_app): app = make_notebook_app() app._link_jupyter_server_extension(jp_serverapp) app.initialize() return app这为扩展作者提供了参考:开发自己的服务端扩展时,可以利用 Jupyter Server 的pytest_jupyter测试工具与jp_serverappfixture 完成集成测试。
配套迁移:服务端导入路径的更新
编写或维护服务端扩展时还有一个高频迁移点:Python 导入路径的变化。在 Notebook 7 中,原本由notebook包导出的服务器模块已经由jupyter_server包接管(详见 docs/source/migrating/server-imports.md)。
需要更新的典型示例:
# Notebook 7 之前(经典 Notebook Server) from notebook.auth import passwd passwd("foo")# Notebook 7 之后(Jupyter Server) from jupyter_server.auth import passwd passwd("foo")另一个示例:
# Notebook 7 之前 from notebook import notebookapp notebookapp.list_running_servers()# Notebook 7 之后 from jupyter_server import serverapp serverapp.list_running_servers()如果你的代码中还有大量对notebook包服务端模块的导入,务必按上述模式逐一核对调整。
迁移自检清单
综合本文内容,从经典 Notebook 迁移到 Notebook 7 并复用/开发服务端扩展时,建议按以下清单逐项确认:
- 确认服务端架构:Notebook 7 已基于 Jupyter Server,
jupyter notebook启动的是 Jupyter Server 进程,可与其他前端共存于同一服务器; - 复用既有服务端扩展:优先尝试直接安装使用,
jupyter server extension list可查看启用状态; - 检查前端扩展:Notebook < 7 或 NBClassic 的前端扩展不兼容,需寻找 JupyterLab/Notebook 7 兼容版本;
- 更新 Python 导入:将
notebook包的服务端模块导入迁移到jupyter_server包; - 编写新扩展时:参照
_jupyter_server_extension_paths/_jupyter_server_extension_points声明入口,用jupyter_server_config.d配置片段启用,并利用pytest_jupyter的jp_serverapp完成集成测试。
结语
Notebook 7 迁移到 Jupyter Server 是一次深刻的架构升级,它让 Notebook 从“一个独立的服务器应用”转变为“Jupyter Server 生态中的一个前端与扩展”。对运维者而言,这意味着服务端扩展生态的直接复用;对开发者而言,这意味着可以使用 Jupyter Server 的标准扩展机制来扩展 Notebook 7。理解这一架构转换,是在 Notebook 7 时代顺利迁移、高效开发的关键一步。
进一步阅读本仓库的迁移系列文档:前端扩展迁移、服务端导入迁移、多界面共存,以及迁移总览 migrate_to_notebook7.md。
【免费下载链接】notebookJupyter Interactive Notebook项目地址: https://gitcode.com/GitHub_Trending/no/notebook
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考