把 Jupyter Notebook 搬到鸿蒙 PC:同栈双胞胎的 Notebook-first 移植实战
把 Jupyter Notebook 搬到鸿蒙 PC同栈双胞胎的 Notebook-first 移植实战欢迎加入开源鸿蒙 PC 社区https://harmonypc.csdn.net/欢迎在 PC 社区平台申请新建项目https://atomgit.com/OpenHarmonyPCDeveloper适配开源地址https://atomgit.com/OpenHarmonyPCDeveloper/ohos_jupyterNotebook写在前面这是最有意思的一篇——因为它不是从零开始移植一个应用而是从已经跑通的姊妹工程里分叉出另一个产品形态。Jupyter 生态里有个特殊现象Notebook 7 的前端就是 JupyterLab 组件构建的。上游jupyter/notebook从 7.0 开始放弃了老nbclassic的 jQuery 代码库改为复用 Lab 的 React/Phosphor 前端。这意味着如果你已经把 JupyterLab 移植到了鸿蒙 PC你就已经顺手完成了 Jupyter Notebook 90% 的移植工作——剩下的是产品身份分叉和 UI 形态收敛。任务清单要求两个产品分列交付、独立安装、独立评分所以这次的核心问题不是「能不能跑」Lab 已经验证而是「怎么把一套已验证的技术栈切成两个能共存、可独立演进的交付物」。一、为什么 Notebook 7 是「最容易的硬骨头」先看清楚上游关系jupyter/notebook (Notebook 7) │ 前端复用 ▼ jupyterlab/jupyterlab (Lab 组件库) │ OHOS 适配已验证姊妹工程 ohos_JupyterLab ▼ OpenHarmony Electron (libelectron.so) node-static 浏览器内 PythonNotebook 7 Lab 前端 single-document 外壳。上游用pageConfig控制产品形态配置JupyterLab 产品Jupyter Notebook 产品pageConfig.modemultiple-documentsingle-document启动 URL/labLauncher 多文档入口/lab/tree/Untitled.ipynb直接打开笔记本Launcher 卡片页有禁用左侧文件浏览器有禁用TOC 侧栏有禁用bundleNameorg.jupyter.lab.ohosorg.jupyter.notebook.ohos环境变量前缀JUPYTERLAB_*NOTEBOOK_*兼容JUPYTERLAB_*所以移植策略非常清晰fork 姊妹工程 → 改产品身份配置 → 保持技术栈完全复用。二、从 Lab 分叉bootstrap 脚本做了什么两个仓库之间用一个 bootstrap 脚本同步 runtime约 2000 行 Electron 主进程代码不重复维护nodescripts/bootstrap-from-notebook.mjs# Notebook → 姊妹方向nodescripts/bootstrap-from-lab.mjs# 反向Lab 仓库持有源脚本做的字符串/配置级重写org.jupyter.lab.ohos → org.jupyter.notebook.ohos productUi: lab → productUi: notebook /labLauncher 入口 → /lab/tree/Untitled.ipynb JUPYTERLAB_*优先 → NOTEBOOK_*优先JUPYTERLAB_* 兼容 hnpPackages type: private → type: public ← 关键差异见 §四工程判断这种「同栈双产品」的架构下bootstrap 脚本就是唯一的真相源。所有产品身份相关的东西都集中在这一个脚本里避免两个仓库手工 drift。三、架构和 Lab 完全同栈只有入口不同三种服务模式与 Lab 完全一致模式环境变量场景node-static默认NOTEBOOK_OHOS_SERVER_MODEnode-static静态前端 浏览器内内核零原生依赖pythonNOTEBOOK_OHOS_FORCE_PYTHON1设备上跑python -m jupyterlab需 aarch64 发行版externalNOTEBOOK_EXTERNAL_SERVER_URL…连接已有 Jupyter Server为什么默认 node-static 而不是 python 模式pyzmq/libsodium 在设备侧仍然脆弱官方文档原话交叉编译一个能跑 Jupyter Server 的 Python 环境的工程成本远超「静态前端 浏览器内解释器」的方案。这是整个 Jupyter 双胞胎移植里最重要的一个工程决策。四、HNP 双胞胎共存机制本次最大坑两个产品都打包了一个 HNP 原生包jupyterlab_python.hnp用于可选的原生 Python 能力。第一次装 Notebook 时直接翻车Install Failed: code:9568407 Failed to install the HAP because installing the native package failed.hilog 关键线索ProcessBundleInstallNative … hnp install: electron [HNP API] native package install! … package nameorg.jupyter.notebook.ohos already exist cfg ignore … MSG_ERR_NATIVE_INSTALL_FAILED根因HNP 包有public/private两种作用域类型作用域冲突规则public设备全局唯一同名 public 包只能装一个private单应用沙箱每个应用各持一份互不干扰两个产品声明了同名jupyterlab_python.hnp如果都是 public先装的占坑后装的报 9568407。修复方案不对称设计// Notebook先发布占 public 坑 hnpPackages: [ { package: jupyterlab_python.hnp, type: public } ] // Lab后发布用 private 共存 hnpPackages: [ { package: jupyterlab_python.hnp, type: private } ]改完必须重新assembleHap——模块元数据是烘焙进 HAP 的热改无效。方法论任何「同栈双胞胎」交付都要在 HNP 这一层显式设计共存策略且不对称一个 public 一个 private是最稳的——对称 public 会互相踢对称 private 浪费设备空间且语义不明。五、真机验收六个功能点逐一过设备HUAWEI MateBook ProHarmonyOS 7.0.0。5.1 启动直达笔记本single-document 的核心体验这就是 Notebook-first 与 Lab-first 的用户可感知差异打开就是笔记本光标在 cell 里可以直接打代码。Click to add a cell.提示、Mode: Command/Edit状态切换、Ln x, Col y行列号全部工作。5.2 Cell 执行与返回值显示注意[3]: None这一行——这是 Jupyter 对表达式返回值的自动回显print()返回 None。这个细节存在说明 Skulpt 内核的执行协议和前端的消息通道是完整实现的不是简单地把 stdout 打到页面上。5.3 菜单完整度20 菜单项、快捷键提示、二级菜单全部渲染正确。右下角还能看到系统任务栏BOSS 直聘、邮件、抖音——这是真机全屏截图不是模拟器。5.4 键盘快捷键帮助弹窗、滚动、关闭交互全部正常——Lab 前端的 Modal 组件在 OHOS Electron 上没有降级。5.5 ASCII 艺术字输出多行字符串渲染值得记录的一个细节这些 box 字符╔═╗║╚╝在r...raw 三引号字符串里会触发 Skulpt 词法器 bugSyntaxError: bad input改用普通...三引号或分行print()就完全正常。截图里的输出就是修复后的结果——这是 Skulpt 内核的边界不是平台问题。5.6 无 matplotlib 环境下的数据可视化本文最有价值的一节鸿蒙 PC 的 Jupyter 双胞胎默认内核是 Skulpt没有 matplotlib / numpy。但数据可视化需求是真实的——教学场景画个函数曲线、演示趋势不能没有。解法是纯标准库 ASCII 折线图完整代码约 40 行纯math 列表推导Skulpt 100% 兼容importmath# 1. 数据xs[i*0.4foriinrange(24)]ys[math.sin(x)*3x*0.25forxinxs]# 2. 画布W,H64,18min_y,max_ymin(ys),max(ys)min_x,max_xmin(xs),max(xs)defto_col(x):returnint((x-min_x)/(max_x-min_x)*(W-2))1defto_row(y):returnint((y-min_y)/(max_y-min_y)*(H-2))# 3. 画布初始化 坐标轴canvas[[ for_inrange(W)]for_inrange(H)]forrinrange(H):canvas[r][0]│forcinrange(W):canvas[H-1][c]─canvas[H-1][0]└# 4. 描点 插值连线foriinrange(len(xs)):colto_col(xs[i])rowH-1-to_row(ys[i])canvas[row][col]●ifi0:prev_colto_col(xs[i-1])spancol-prev_colifspan1:forcinrange(prev_col1,col):t(c-prev_col)*1.0/span yys[i-1](ys[i]-ys[i-1])*t canvas[H-1-to_row(y)][c]·# 5. 峰谷标注peak_iys.index(max(ys))low_iys.index(min(ys))canvas[H-1-to_row(ys[peak_i])][to_col(xs[peak_i])]▲canvas[H-1-to_row(ys[low_i])][to_col(xs[low_i])]▼# 6. 输出print(y_max {:.2f}.format(max_y))forrowincanvas:print(.join(row))print(y_min {:.2f} x: {:.1f} - {:.1f}.format(min_y,min_x,max_x))几个工程要点刻意不用 f-string部分 Skulpt 版本支持不稳全部.format()刻意不用 raw stringr是词法坑box 字符只出现在普通短字符串里插值连线拆成span/t/y三个中间变量避免长链表达式触发解析器边界[i]: None返回值回显、错误行号定位bad input on line N都正常工作这套「降级可视化」思路适用于任何没有图形栈的嵌入式 Python 环境——Skulpt、MicroPython、受限容器都是同一个问题域。六、双胞胎工程的坑位对照这次 Notebook 分叉把 Lab 踩过的坑原样再踩一遍但每个坑的解法都能直接复用成本大幅下降坑Lab 首次解决成本Notebook 复用成本CompileArkTS 10705000import lazy排查半天定位到compatibleSdkVersionStage: beta10bootstrap 直接钉住6.0.1(21)SignHap 00303074profile 绑 bundle摸清 debug profile 的 bundle 绑定机制5 分钟DevEco Fix 一次Install 9568320signingConfig: 半小时发现 DevEco 不回填 products 引用5 分钟知道看产物文件名Install 9568407HNP 冲突理解 public/private 作用域0bootstrap 写好publicresfile 放错模块白屏半天0脚本生成正确路径这就是「同栈双胞胎」模式的最大红利第一个产品的踩坑成本是沉没成本第二个产品的边际成本趋近于零。反过来如果两个产品各自独立移植这些坑要踩两遍。七、复现命令cdohos_JupyterNotebook# 1. 从 Lab 工程同步 runtime首次必做nodescripts/bootstrap-from-lab.mjs# 或按仓库实际脚本名# 2. 打包 runtime 到 web_engine resfilenodepkg/ohos/build-package.mjs# 3. 构建 HAPnodepkg/ohos/build-hap.mjs# 跳过 hvigor 仅打包资源# NOTEBOOK_OHOS_SKIP_HVIGOR1 node pkg/ohos/build-hap.mjs# 4. DevEco 自动签名 → 检查 products[].signingConfig default# 5. 安装 启动hdcinstall-relectron/build/default/outputs/default/electron-default-signed.hap hdc shell aa start-aEntryAbility-borg.jupyter.notebook.ohos环境变量速查NOTEBOOK_PORT8888、NOTEBOOK_TOKEN默认随机、NOTEBOOK_ROOT_DIRuserData/notebooks、NOTEBOOK_DISABLE_GPU1。八、给「同栈多产品」交付的方法论这套模式适用于所有「一个技术栈要交付多个产品形态」的场景IDE 的社区版/专业版、浏览器的稳定版/测试版、办公套件的多个组件先跑通一个再分叉第二个——第一个产品的踩坑日记就是第二个产品的施工图bootstrap 脚本是唯一真相源——产品身份的所有差异集中在一个可 review 的 diff 里禁止手工双仓库漂移HNP/权限/签名按 bundle 隔离——debug profile 绑 bundleNameHNP 设计不对称共存public/private一个都别复用UI 形态差异交给上游配置——pageConfig.mode这种官方开关比魔改前端代码稳定一个数量级降级路径先于完整路径——node-static 浏览器内内核先落地原生 Server 后补能跑的 60 分比跑不起来的 100 分有价值受限环境的可视化用 ASCII——没有图形栈时40 行纯标准库代码就能覆盖教学场景 80% 的画图需求回头看这个项目最大的价值不是「又移植了一个应用」而是验证了同栈双胞胎的工程模式Notebook 7 的分叉只花了 Lab 首次移植约 20% 的时间而这 80% 的节省全部来自 Lab 留下的踩坑记录和 bootstrap 脚本。如果你手上也有类似「一个底座多个产品」的移植任务强烈建议按这个模式组织仓库——第一个产品慢一点没关系它是在为后面的所有产品铺路。常见问题 FAQQ1和 JupyterLab 版有什么区别能同时装吗能共存。两者技术栈完全相同差异只在产品形态Notebook 打开就是单个笔记本single-document无 Launcher / 文件浏览器Lab 是多文档 Launcher。HNP 层做了不对称设计Notebook 用public、Lab 用private互不冲突。Q2为什么打开后不是经典的/tree老界面上游 Notebook 7 已经放弃老nbclassic的 jQuery 前端改为复用 Lab 组件。本工程走的是官方路线——Lab 静态资源 pageConfig.mode single-document视觉上是「单文档笔记本」但底层不是老/tree。Q3能装 numpy / matplotlib 吗默认不能。内核是 Skulpt浏览器内 Python 子集没有 C 扩展生态。两个出路切NOTEBOOK_EXTERNAL_SERVER_URL连远程 Jupyter Server 用真内核或者用纯标准库 ASCII 图表顶住教学场景见 §5.6 的 40 行折线图代码。Q4为什么r...三引号字符串报SyntaxError: bad inputSkulpt 词法器对 raw 三引号 box-drawing 多字节字符有边界 bug。去掉r前缀用普通...或把内容拆成多行print()就正常。真 Python 解释器跑同样代码没问题——这是内核限制不是平台 bug。Q5签名成功了还是报9568320 no signature file看产物文件名。unsigned说明build-profile.json5里products[].signingConfig还是空串——DevEco 自动签名只写材料不回填这个引用。手动改成default重新构建。Q6装了 Lab 再装 Notebook报9568407原生包失败HNP 同名冲突。两个产品的hnpPackages里声明了同名jupyterlab_python.hnppublic类型设备全局唯一后装的会被拒。用新版 HAPNotebookpublic/ Labprivate的不对称组合即可共存不想重编就先卸载另一个再装。

相关新闻

无标题项目管理法:从草稿到爆款的技术创作实践

无标题项目管理法:从草稿到爆款的技术创作实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/17 19:25:23 阅读更多 →
CookLikeHOC 小米南瓜粥标准化配方解析:从 4600g 水批量熬制到家庭小份换算

CookLikeHOC 小米南瓜粥标准化配方解析:从 4600g 水批量熬制到家庭小份换算

CookLikeHOC 小米南瓜粥标准化配方解析:从 4600g 水批量熬制到家庭小份换算 【免费下载链接】CookLikeHOC 🥢像老乡鸡🐔那样做饭。已添加2026年发布的《老乡鸡菜品溯源报告 2.0中新出现的菜品。主要部分于2024年完工,非老乡鸡官方…

2026/9/22 1:57:46 阅读更多 →
当我把四个串口交给 AI:一次 2.4G 双向透传的完整调试闭环

当我把四个串口交给 AI:一次 2.4G 双向透传的完整调试闭环

从“你把日志贴给我看”,到“你直接读串口、发数据、烧固件、统计丢包”,嵌入式开发的协作方式发生了什么变化?一、需求看起来并不复杂 项目使用两块相同的 GD32F303CC Tag 板和 SI24R1 2.4 GHz模块,希望实现一条双向透明串口链路…

2026/9/22 1:57:01 阅读更多 →

最新新闻

3招手写实现提速法,搞定如何提高做题速度

3招手写实现提速法,搞定如何提高做题速度

3招手写实现提速法,搞定如何提高做题速度 刚毕业那会儿,我盯着 LeetCode 题目发呆,Python 语法背得滚瓜烂熟,但一遇到“实现 LRU 缓存”或者“手写 Promise”就脑子空白。这不是你笨,是 学会语法却不知怎么搭项目…

2026/9/22 5:02:14 阅读更多 →
腾讯助手官方下载避坑速查手册:3个致命错误让你少踩10年

腾讯助手官方下载避坑速查手册:3个致命错误让你少踩10年

腾讯助手官方下载避坑速查手册:3个致命错误让你少踩10年 官方文档往往厚达数百页,新手翻两页就晕,根本抓不住重点。我在一线摸爬滚打十年,见过太多人因为“腾讯助手官方下载”这个看似简单的动作,导致项目延期、环境崩溃甚至数据丢失。今天这份…

2026/9/22 5:02:14 阅读更多 →
换边实战指南:3个坑点教你搞定完整示例

换边实战指南:3个坑点教你搞定完整示例

换边实战指南:3个坑点教你搞定完整示例 复制来的代码跑不通,报错信息一堆红字,是不是瞬间头大? 别慌,这通常是环境配置或逻辑细节没对齐。…

2026/9/22 5:02:13 阅读更多 →
lolig队员面试必问:3个核心源码解析避开StackTrace报错

lolig队员面试必问:3个核心源码解析避开StackTrace报错

lolig队员面试必问:3个核心源码解析避开StackTrace报错 满屏红色的StackTrace像天书一样砸在脸上,你甚至分不清哪行是业务代码,哪行是框架内部抛出的。这种崩溃感,每个被【lolig队员】这类小众技术标签“背刺”过的开发者…

2026/9/22 5:02:13 阅读更多 →
3个致命坑:步距角配置错误导致电机抖动,源码解析避坑指南

3个致命坑:步距角配置错误导致电机抖动,源码解析避坑指南

3个致命坑:步距角配置错误导致电机抖动,源码解析避坑指南 刚升级完运动控制库版本,发现电机一通电就狂抖,甚至发出刺耳的啸叫?别慌,这大概率不是硬件坏了,而是你被 步距角 的新 API…

2026/9/22 5:02:13 阅读更多 →
3天搞定逗拍下载:手写实现核心逻辑,避开90%新手坑

3天搞定逗拍下载:手写实现核心逻辑,避开90%新手坑

3天搞定逗拍下载:手写实现核心逻辑,避开90%新手坑 看了一堆教程还是不会写项目?别慌,问题不在你笨,而在你一直在“抄”代码,没在“懂”原理。今天聊的 逗拍下载…

2026/9/22 5:01:13 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →