Mu Editor 鸿蒙 PC 适配全记录:用 Qt 与嵌入式 CPython 重建教学型 Python IDE

欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/

欢迎在 PC 社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

适配开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_MuEditor

环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743

一、为什么选择适配 Mu Editor

Mu Editor 是一款面向 Python 初学者、教师和创客的轻量级编辑器。它没有把重点放在复杂的工程管理或插件体系上,而是围绕"写代码、运行、查看结果、调试、连接开发板"组织操作路径。对刚接触编程的用户来说,这种低干扰的工作流比功能繁多的通用 IDE 更容易理解。

HarmonyOS PC 需要的不只是办公软件,也需要能够覆盖教学、实验和创客场景的开发工具。适配 Mu Editor 的价值有两层:一方面,可以为鸿蒙 PC 补充一款开箱即用的 Python 学习工具;另一方面,Mu 同时涉及 Qt 桌面界面、Python 解释器、文件系统、串口和开发板工作流,能够较完整地检验传统 Python 桌面应用迁移到 HarmonyOS PC 时的技术边界。

上游 Mu Editor 主要使用 Python 与 PyQt5 实现。原工程在 Windows、macOS、Linux 和 Raspberry Pi 上运行时,依赖系统 Python、桌面 Qt、动态安装的第三方包以及各平台的文件和设备接口。这些前提在 HAP 沙箱中并不成立,因此本次工作不是把原入口脚本直接打包,而是在保留上游工程的同时,为鸿蒙端新增独立的 harmony_pc/ 工程。

二、先确定迁移边界:保留产品逻辑,重建鸿蒙运行链路

如果强行把 Python、PyQt5 和全部桌面依赖原样塞进 HAP,短期内或许能得到一个可启动的实验包,但后续会持续受到解释器路径、动态扩展、插件加载、文件权限和设备访问的影响。我们最终采用"独立鸿蒙宿主 + Qt Widgets 界面 + 嵌入式 CPython"的方式,把最关键的使用流程落到可维护的原生工程中。

层次 上游实现 鸿蒙 PC 适配策略
应用入口 Python 启动脚本 ArkTS UIAbility 管理生命周期
桌面界面 PyQt5 Qt for OpenHarmony / Qt Widgets
Python 执行 系统 Python 静态链接的嵌入式 CPython 3.12
编辑能力 PyQt 编辑组件 自定义 CodeEditor 与语法高亮器
文件访问 桌面文件系统 鸿蒙目录权限、文件共享激活与应用沙箱
开发板连接 Python 串口库与模式插件 Qt SerialPort、Raw REPL 与挂载盘部署

这条路线没有修改上游桌面端的启动方式。仓库根目录下的 Python/PyQt5 工程仍可继续用于原平台,鸿蒙相关代码全部放在 harmony_pc/ 中。这样既避免迁移代码侵入上游主体,也为后续同步上游版本留出了空间。

三、鸿蒙端整体架构

鸿蒙端的启动链路如下:

text 复制代码
EntryAbility
    ├── 准备 python_stdlib.zip
    ├── 申请文档与下载目录权限
    └── 加载 Index.ets
            └── NODE 类型 XComponent
                    └── Qt OpenHarmony QPA 插件
                            └── libentry.so
                                ├── Qt Widgets 编辑器
                                ├── 嵌入式 CPython 3.12
                                ├── 调试器与持久 REPL
                                └── Qt SerialPort / QtCharts

主要目录如下:

text 复制代码
ohos_MuEditor/
├── mu/                                  # 上游 Python / PyQt5 实现
├── tests/                               # 上游测试
├── docs/                                # 上游文档
├── README.OpenHarmony_CN.md             # 鸿蒙工程说明
└── harmony_pc/
    ├── AppScope/                        # 应用名称、图标与全局资源
    ├── build-profile.json5              # API 22、产品与签名配置
    ├── qtforharmony_sdk/                # Qt for OpenHarmony SDK
    ├── third_party/cpython/             # CPython 源码及 ARM64 静态库
    ├── scripts/                         # SDK、Python 和验收脚本
    └── entry/src/main/
        ├── ets/                         # Ability 与 XComponent 宿主
        ├── resources/rawfile/           # Python 标准库压缩包
        └── cpp/
            ├── mu_editor_main.cpp       # 主窗口与业务工作流
            ├── code_editor.cpp          # 行号、断点和诊断标记
            ├── python_runtime.cpp       # Python 执行、REPL 与调试
            └── device_service.cpp       # 串口发现、连接与重连

EntryAbility 先把 HAP 资源中的 python_stdlib.zip 写入应用文件目录,再通过启动参数把实际路径交给 Qt 侧。ArkTS 页面只负责创建全屏 XComponent,真正的编辑器窗口由 Qt QPA 插件加载 libentry.so 后构建。这样,鸿蒙生命周期和 Qt 桌面界面之间有一条清晰的边界。

四、核心适配过程

1. 先让 Qt 窗口在鸿蒙 PC 上稳定承载

Qt 窗口并不是独立于鸿蒙页面启动的。工程先由 EntryAbility 创建窗口,再加载 NODE 类型的 XComponent,最后调用 QPA 插件启动 Qt 应用。窗口默认尺寸为 1440×900,同时设置最小尺寸,避免编辑区、输出区和 REPL 输入区在小窗口下相互挤压。

鸿蒙 PC 上既有最大化窗口,也有分屏、浮窗和不同显示缩放。固定宽度工具栏在窄窗口中很容易把后半部分操作截断,因此适配中增加了工具栏溢出菜单:宽度不足时收起低优先级动作,并通过右侧展开入口提供完整操作。这个处理看似属于界面细节,实际会直接影响 Run、Debug、Devices 等关键按钮能否在各种窗口状态下使用。

以下画面均为本项目签名 HAP 安装到 HarmonyOS PC 2in1 真机后的实际运行截图,设备截图分辨率为 3120×2080。

2. 重建编辑器,但不把它做成普通文本框

鸿蒙端使用自定义 CodeEditor 实现代码编辑区域,并补齐了教学型 Python IDE 所需的基本反馈:行号、Python 语法着色、括号匹配、当前行显示、断点栏、搜索高亮和诊断行标记。多标签页分别保存文件路径、修改状态、编码与换行符信息,关闭有未保存内容的标签时会给出保存、放弃或取消选项。

文件保存使用 QSaveFile 提交,尽量避免写入中断后留下半个文件。应用还实现了最近文件、会话恢复和 30 秒自动保存;在设置中可以选择保存时清理行尾空白,并为 Python 运行配置环境变量。

打开文件时会识别 UTF-8 BOM,并区分 UTF-8 与兼容的单字节编码;保存时保留原换行格式。当前支持的文件过滤器覆盖 Python、HTML、CSS、JavaScript、JSON 和普通文本,文件也可以直接拖入窗口打开。

3. 把 CPython 变成 HAP 内真正可执行的运行时

Mu 的核心不是"编辑 Python 文本",而是让代码能在本机执行。工程将 CPython 3.12 交叉编译为 arm64-v8a 静态库,并与 libentry.so 一起链接。Python 标准库被整理为 python_stdlib.zip 放进 HAP,应用每次启动都会刷新沙箱中的标准库副本,避免升级后继续使用旧资源。

解释器使用 PyConfig_InitIsolatedConfig 初始化,关闭用户级 site 目录和外部环境干扰,并显式设置模块搜索路径。运行文件时会设置真实的 __file__、脚本工作目录和首位 sys.path,因此脚本能够读取自身路径,也能导入同目录模块。

代码执行放到 QtConcurrent 任务中,标准输出和错误输出重定向到内存流,执行结束后再回到界面线程展示。这样,普通脚本运行不会把窗口长时间卡死;停止按钮则通过 Python 中断机制请求终止当前任务。

4. REPL 需要保存上下文,而不是每次重新启动解释器

教学场景经常需要边讲边试。鸿蒙版保留同一份 Python 全局字典作为交互上下文,用户在 REPL 中定义的变量和导入的模块可以继续用于后续命令。输入框支持回车执行以及上下方向键浏览命令历史;如果已经连接 MicroPython 设备,同一个输入区会把命令发送到设备 REPL,而不是本地解释器。

5. 查找、替换和诊断要形成可见反馈

查找功能支持当前文档定位、上一处、下一处和全部匹配高亮;替换会在一个编辑事务中完成全部命中项的修改。Check 操作使用内置 AST 分析语法错误、未使用导入等基础问题,并把对应行号交给编辑器侧显示诊断标记。

这部分没有简单复用桌面端完整的 pyflakes/pycodestyle 依赖,因为当前 HAP 尚未打包这些第三方模块。内置检查覆盖范围较小,但好处是运行时边界明确,不会在真机上因为缺少 Python 包而失效。

6. 调试器必须处理 Python 线程与 Qt 界面的同步

鸿蒙端调试器基于 Python trace 机制实现,支持断点、继续、单步进入、单步跳过和单步跳出。解释器暂停时会通过线程安全回调把当前行和局部变量交给 Qt 主线程,编辑器跳转到相应代码行,右侧调试面板同步刷新;用户发出下一步命令后,等待中的 Python 任务再继续执行。

这里最容易出现的问题是直接从解释器线程操作 Qt 控件。Qt Widgets 只能由界面线程安全更新,因此调试事件必须使用队列方式切回主线程;调试命令则通过互斥量和条件变量传回 Python 任务。只有把这两个方向都处理好,暂停、查看变量和继续执行才不会造成随机卡死。

7. 为开发板工作流建立统一设备层

Mu Editor 与普通文本编辑器最大的差异,是它面向 micro:bit、ESP MicroPython、CircuitPython 和 RP2040 等设备。鸿蒙端使用 Qt SerialPort 枚举串口,根据设备信息建议模式,并提供断线重连。连接后可以进入普通 REPL 或 Raw REPL,执行当前代码,以及列出、上传、下载和删除设备文件。

对于 CircuitPython 和 RP2040,应用还会识别 CIRCUITPYRPI-RP2PICO 等挂载盘,把代码部署为 code.pymain.py。micro:bit 的固件入口可以把用户选择的 HEX 文件复制到 MICROBIT 磁盘。这里需要明确:当前版本不会把编辑区源码动态注入 HEX,ESP 专用的固件擦除和烧录也尚未内置。

模式选择器保留了 Python 3、micro:bit、ESP MicroPython、CircuitPython、RP2040、Pygame Zero 和 Web 七类入口。不同模式共用编辑器、输出区和资源管理基础能力,再按运行目标切换本地 CPython、串口或挂载盘流程。

五、适配中遇到的主要困难

难点一:PyQt 应用不能等同于"复制一个 Python 环境"

上游工程默认系统已经准备好 Python、PyQt5 和一组可安装的依赖,但 HAP 必须自己携带运行时和资源。解释器库、标准库、Qt 平台插件、图像插件以及 ArkTS 字节码都要进入同一安装包,并且每一项都必须是 ARM64 目标产物。主机侧工具与目标侧动态库混用,会在配置、链接或真机加载阶段产生完全不同的错误。

最终工程把 CPython 静态链接到 libentry.so,标准库单独压缩,并在构建产物上检查 ELF 架构、运行路径和关键 Python 扩展符号。这比只看"构建成功"更可靠,因为很多问题只有拆开 HAP 后才能确认。

难点二:标准库所在位置在构建时和运行时完全不同

HAP 中的 rawfile 不能直接假设为普通磁盘路径。ArkTS 侧需要读取资源内容并写入应用文件目录,Qt 侧再从真实沙箱路径初始化 Python。适配中还选择每次启动都刷新压缩包,避免应用升级后旧标准库残留在沙箱中,造成解释器与库版本不一致。

难点三:文件权限不只是弹出一次授权框

鸿蒙 PC 的文档目录、下载目录和外部文件都受到权限与沙箱约束。应用声明并请求相应目录权限,Qt 打开共享文件前还会激活鸿蒙文件访问能力。保存则使用原子提交,避免用户授权、存储异常或应用退出时破坏原文件。

难点四:Python 的 GIL 与 Qt 线程模型必须同时满足

为了避免界面阻塞,运行和调试都放到后台任务;但 CPython 要求进入解释器时持有 GIL,Qt 又要求界面更新发生在主线程。运行时初始化后释放主线程状态,每次任务进入 Python 时重新获取 GIL;输出、状态栏和调试面板的更新则切回 Qt 事件循环。这个线程边界如果处理不完整,表现通常不是稳定的编译错误,而是偶发无响应或退出。

难点五:桌面大屏并不意味着可以无限横向堆按钮

Mu 的高频操作很多,全部放进一行工具栏在 3120×2080 真机最大化时没有问题,但进入分屏或浮窗后会迅速溢出。适配中按窗口宽度动态保留高频动作,并把其余入口收进菜单,同时调整了默认窗口和最小窗口尺寸。这个改动保证了界面缩放以后功能仍然可达,而不是只在截图尺寸下看起来完整。

六、编译、安装与启动

当前工程面向 HarmonyOS SDK API 22,目标架构为 arm64-v8a,设备类型声明为 2in1tablet。使用 DevEco Studio 时,应直接打开仓库中的 harmony_pc/ 目录,等待工程同步完成后,为包名 com.codewith.mu.editor 配置与当前设备匹配的调试签名。

首次命令行构建前,先准备项目本地的 SDK 兼容视图:

bash 复制代码
cd harmony_pc
./scripts/prepare-sdk-compat.sh

然后执行 HAP 构建:

bash 复制代码
export DEVECO_SDK_HOME="$PWD/.harmony-sdk"
export JAVA_HOME=/Applications/DevEco-Studio.app/Contents/jbr/Contents/Home

/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw assembleHap \
  --mode module -p product=default -p module=entry@default

构建产物位于:

text 复制代码
harmony_pc/entry/build/default/outputs/default/
├── entry-default-unsigned.hap
└── entry-default-signed.hap

安装和启动命令如下:

bash 复制代码
hdc install -r harmony_pc/entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.codewith.mu.editor -m entry

工程还提供两项构建侧验收:

bash 复制代码
node harmony_pc/scripts/verify-feature-parity.mjs
./harmony_pc/scripts/audit-unsigned-hap.sh

前者检查功能矩阵中的源码证据,后者检查 HAP 内的 ARM64 原生库、运行路径、ArkTS 产物、Python 标准库和必要符号。它们不能替代真机操作,但可以尽早发现漏打包和架构错误。

七、当前已覆盖能力与功能边界

目前已经形成可用的 Python 教学主线:

  • 多标签新建、打开、保存、另存为、重命名、拖放、最近文件和会话恢复;
  • 行号、Python 语法着色、括号匹配、缩进、注释、查找替换、跳转和缩放;
  • 嵌入式 CPython 3.12、本地脚本运行、停止、输出与错误捕获;
  • 持久 REPL、命令历史、断点、继续、单步操作和局部变量查看;
  • 基础语法与风格检查、诊断行标记、代码空白整理和实时数字绘图;
  • 串口发现、MicroPython REPL、设备文件传输和 main.py 部署;
  • CircuitPython、RP2040 挂载盘部署,以及 Pygame Zero/Web 项目资源目录管理;
  • 浅色/深色主题、设置持久化、工具栏溢出和鸿蒙 PC 窗口适配。

当前没有把以下能力描述为已完成:

  • 图形化 Python 包安装与管理员模式;
  • 完整 pyflakes/pycodestyle 规则集;
  • 第三方 Python 教学包的整体打包;
  • ESP 固件擦除与烧录;
  • Pygame Zero 游戏运行时;
  • Flask 服务、内置浏览器和部署后端;
  • 将编辑区源码注入 micro:bit HEX 的完整工作流。

开发板相关能力还会受到具体型号、固件版本、USB 权限和挂载状态影响。没有连接对应硬件时,应用会明确提示未发现串口或挂载盘,不会把"界面已有入口"等同于硬件已经完成兼容验证。

八、总结

Mu Editor 的适配说明,Python 桌面应用迁移到 HarmonyOS PC 时,关键工作不在于把入口脚本换一个启动命令,而在于重新建立可信的运行边界:由 ArkTS 管理应用生命周期和权限,由 XComponent 与 Qt QPA 承载原生桌面界面,由嵌入式 CPython 提供稳定、可控的执行环境,再把文件、线程和设备访问接入鸿蒙系统。

当前版本已经打通从代码编辑、保存、运行、查看输出、交互式试验到断点调试的主要闭环,并为常见 MicroPython 开发板保留了统一的串口和部署路径。对于教学型 IDE 而言,这些能力比简单展示一个编辑器首页更重要,也为后续补充第三方 Python 包、完善设备固件工具和扩展课程资源提供了可持续的工程基础。

相关推荐
鸽芷咕1 小时前
MongoDB 鸿蒙 PC 适配全记录:从 Bazel 交叉编译到 HNP 原生数据库服务
数据库·mongodb·harmonyos
长友cy1 小时前
官方示例scene graph - vulkan阅读
qt
微软技术分享1 小时前
基于 HuggingFace Tokenizers 训练自定义分词器
python·ubuntu·大模型·huggingface
安好说AI1 小时前
Flutter for OpenHarmony 实战:媒体选择库 adaptive_image_picker 的鸿蒙化适配全解读
flutter·harmonyos·媒体
gf13211111 小时前
python_调用远程服务器上的openclaw
服务器·python·php
lbb 小魔仙1 小时前
Jupyter Notebook / Lab 深度配置指南:插件 + 内核 + 远程访问 + 容器化部署
ide·python·jupyter
2601_962300471 小时前
python是跨平台的吗
python·开源·跨平台·面向对象·
2401_844582951 小时前
软件架构设计与持续重构:模块化开发实战建
python
朽棘不雕1 小时前
Qt背景(简单了解Qt)
qt