内容#
本节介绍了内容如何在 JupyterLite 网站上集成以及如何使用它。
内核内的访问#
默认情况下,通过默认文件浏览器访问的内容独立于在执行内核内访问的内容。 使文件对内核可用可能取决于内核的实现方式。
Emscripten 内核#
使用 Emscripten 的内核(如 pyodide 或 xeus 内核)依赖于 Emscripten 文件系统 来访问其内容。 对于这种情况,@jupyterlite/contents
提供了一个 DriveFS
辅助类,可用于在 Emscripten 文件系统中挂载文件
const mountpoint = '/drive';
const { FS, PATH, ERRNO_CODES } = /* provided by the emscripten module */;
const { baseUrl } = options;
const { DriveFS } = await import('@jupyterlite/contents');
const driveFS = new DriveFS({
FS,
PATH,
ERRNO_CODES,
baseUrl, // Website base URL
driveName: 'my-drive', // Any name of your choosing
mountpoint,
});
FS.mkdir(mountpoint);
FS.mount(driveFS, {}, mountpoint);
FS.chdir(mountpoint);
挂载驱动器后,Jupyter Server 内容(在文件浏览器中显示的内容)将在内核中以 /drive
文件夹的形式提供。
DriveFS
需要网站基本 URL 来从主应用程序请求其内容。 深入了解驱动器架构将阐明这一点。
在 JupyterLite 中运行内核时,会使用三个线程。
主线程:它执行主用户界面,并了解文件浏览器的内容。
内核 Web 工作者:它执行内核(例如,评估来自主线程的笔记本中的代码片段)。它将一个
DriveFS
挂载到 Emscripten 文件系统中。服务工作者:它从缓存中提供网站资产(以便离线工作)。它还可以捕获任何其他网络请求。
假设内核执行以下 Python 代码片段,将内容写入文本文件。
Path("dummy.txt").write_text("Writing on Emscripten filesystem")
以下是执行文件系统操作时发生的交互简化序列。
当代码与文件系统交互时,它会与 Emscripten 虚拟文件系统 交互。该虚拟文件系统允许经典代码(如本例中的 Python 代码片段)在几乎无需更改的情况下运行。此外,虚拟文件系统允许开发人员通过 文件系统 API 提供自己的文件系统 I/O 处理机制。在序列中,我们将触发的 API 简化为单个 put
(实际上,在写入文件时会发生多次调用)。由于我们插入了一个自定义驱动实现 DriveFS
,因此 put 解析将由该代码负责。现有的逻辑是启动一个 POST HTTP 请求,该请求在 /api/drive
端点上,其主体描述了要执行的文件系统操作。在本例中,它看起来像
{
"method": "put",
"path": "/dummy.txt",
"data": { "format": "text", "data": "Writing on Emscripten filesystem" }
}
该请求旨在由服务工作者捕获(在 @jupyterlite/server
包中定义)。服务工作者将通过 BroadcastChannel
(名为 /api/drive.v1
)中的消息将 HTTP 请求转发到主线程。
该消息将由 BroadcastChannelWrapper
捕获,该包装器在插件 @jupyterlite/server-extension:emscripten-filesystem
中实例化。该包装器了解 Jupyter 内容管理器,以便回答请求。例如,在 put
操作的情况下,将调用内容管理器的 save
方法。
然后,回复将通过广播通道、网络请求等传播回 Emscripten 文件系统。
使用 HTTP 请求的必要性导致了使用异步 API(即 Jupyter 内容管理器)回答同步 API(即 Emscripten 文件系统)的约束。
这种架构使 Lite 内核能够从自定义 JupyterLab 驱动 访问内容,从而拥有多个内容来源。