鸿蒙PC迁移:jieba 中文分词 Python 三方库鸿蒙PC适配全记录
欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区:https://harmonypc.csdn.net/
项目开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_jieba
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
这篇文章记录的是一次把 Python 中文分词三方库 jieba 接入 HarmonyOS PC / 鸿蒙 PC 应用的完整过程,包括踩到的几个真实问题和最终怎么修好的。
jieba 和很多桌面软件不一样,它本身不是一个现成的 GUI 程序,而是 Python 生态里最常用的中文分词库之一。它可以做精确分词、全模式分词、搜索引擎分词,也能做词性标注和关键词提取。也就是说,这次适配的重点不是“把一个窗口搬到鸿蒙 PC 上”,而是要解决一个更通用的问题:
鸿蒙 PC 应用如何调用 HNP Python 里的 Python 三方库,并把它做成真实用户可以操作的工具?
最终我们在项目里新增了一个 examples/harmony_pc/ 示例工程。它是一个面向鸿蒙 PC 用户的中文分词工具:用户可以直接输入或从文件载入一段中文文本,选择分词 / 词性标注 / 关键词提取,再把结果导出成文本文件。

一、项目背景:jieba 是什么
jieba(结巴分词)是 Python 生态中使用面非常广的中文分词库,几乎是中文 NLP 入门必用的工具。它常见的能力包括:
- 精确模式分词:尽量准确地切分句子,适合文本分析;
- 全模式分词:把句子里所有能成词的片段都切出来;
- 搜索引擎模式分词:在精确模式基础上,对长词再切一刀,适合建索引;
- 词性标注:给每个词标上名词、动词、地名等词性;
- 关键词提取:用 TF-IDF 或 TextRank 算法从文本里挑出关键词。
这次鸿蒙 PC 示例就是把 jieba 包装成一个普通用户能直接用的小工具:粘贴一段中文,选一个操作,点一下就能看到分词结果,还能把结果导出。
这里有一个对适配非常友好的关键点:jieba 是纯 Python 库,只依赖 Python 标准库,没有 NumPy、OpenBLAS、FFmpeg 这类需要本地编译的依赖(它的 paddle 模式是可选的,本示例不启用)。这一点后面会反复用到,它直接决定了我们可以走一条比图像、科学计算类库更简单、更稳的适配路线。
二、路线选择:不重写 jieba,而是通过 HNP Python 调用
适配前先分析了两条路线。
第一条是把中文分词能力用 ArkTS 或 Native 重写。中文分词涉及词典、HMM 模型、Viterbi 解码、TF-IDF / TextRank 等一整套算法,重写成本高、易出错,不适合第一版适配。
第二条是保留 Python 三方库,让鸿蒙应用通过 HNP Python 调用 jieba。鸿蒙 PC 上可以准备 HNP Python 环境,应用侧只负责输入文本、组织参数、展示结果,真正的分词仍然交给 Python。
最终采用第二条路线:
鸿蒙 ArkTS 页面
-> JiebaHnpClient 写入 JSON 请求
-> Native/N-API 模块启动 HNP Python(放在 TaskPool 工作线程)
-> jieba_hnp_bridge.py import jieba
-> jieba 执行分词 / 词性标注 / 关键词提取
-> Python stdout 返回 JSON
-> ArkTS 解析结果并导出文件
这条路线的好处是:
- 不需要重写 jieba;
- 复用 Python 生态里成熟的中文分词能力;
- 适合 Python 三方库向鸿蒙 PC 工具化迁移;
- 后续要加新能力时,主要扩展 Python bridge 和 ArkTS client 即可;
- Native 层只做桥接,不承担分词业务逻辑。
而且因为 jieba 是纯 Python,没有平台相关的编译产物,我们还能再进一步:把 jieba 的源码和词典直接打包进 HAP,让设备端连 pip install jieba 都省掉。这一点在第五节细说。
三、先确认 HNP Python 能跑通(必须先装「Python 安装器」)
在写鸿蒙 UI 之前,第一步不是画页面,而是确认目标设备上的 HNP Python 能不能正常启动。这个 HAP 示例负责页面、文件选择、Native 桥接和调用流程,但真正执行分词的,是设备里的 HNP Python。
⚠️ 重点:鸿蒙 PC 上默认不一定有可供应用调用的 Python 环境。普通用户在使用这个软件之前,必须先在鸿蒙 PC 的应用市场里搜索并安装「Python 安装器」,再用它把 Python 运行环境装到鸿蒙 PC 上。 没有这一步,应用启动 HNP Python 会直接失败。
1. 在鸿蒙 PC 应用市场安装「Python 安装器」
打开鸿蒙 PC 的应用市场,搜索 Python 安装器 并安装。安装完成后打开它,按页面提示完成 Python 运行环境安装。这一步做完,设备上才会出现本示例默认使用的 HNP Python 路径:
/data/service/hnp/python.org/python_3.12/bin/python3.12

2. 确认 HNP Python 能正常启动
在鸿蒙 PC 的 HiShell 或系统终端里执行:
/data/service/hnp/python.org/python_3.12/bin/python3.12 --version
能看到 Python 版本号,说明基础环境就绪。如果提示文件不存在,通常是「Python 安装器」还没装,或者还没完成 Python 环境初始化。
3. jieba 不需要在设备上单独安装
这一点和大多数 Python 三方库适配不同。像 imageio、fontTools 这类库,通常还要用同一个 HNP Python 去 pip install。但 jieba 是纯 Python 库,我们直接把它随应用打包了,所以设备端不需要 pip install jieba,只要 python3.12 能跑起来就行。
如果你确实想用设备端 pip 安装的 jieba,把示例里 rawfile/python/jieba/ 目录删掉即可,worker 会回退到 HNP Python 里已安装的 jieba。
4. 本地命令行自检
在接 ArkTS 之前,可以先在鸿蒙 PC 的 HNP Python 里跑一遍命令行自检:
cd examples/harmony_pc
export PYTHONDONTWRITEBYTECODE=1
export JIEBA_CACHE_DIR=./jieba-cache
python3.12 jieba_hnp_demo.py
如果这里失败,说明问题还在 Python 环境阶段,鸿蒙应用里调用也不会成功。先把 HNP Python 侧跑通,后面的 ArkTS 和 Native 桥接才有意义。
四、新增鸿蒙 PC 示例工程
适配完成后,项目新增了鸿蒙 PC 示例目录:
examples/harmony_pc/
AppScope/
entry/
hvigor/
build-profile.json5
oh-package.json5
jieba_hnp_bridge.py
jieba_hnp_demo.py
run_hishell.sh
sample_request.json
真正的鸿蒙应用工程就在 examples/harmony_pc。几个关键文件:
entry/src/main/ets/pages/Index.ets
entry/src/main/ets/jieba/JiebaHnpClient.ets
entry/src/main/ets/native/JiebaHnpNative.ets
entry/src/main/ets/util/RawFileSync.ets
entry/src/main/cpp/napi_init.cpp
entry/src/main/cpp/types/libjieba_hnp_bridge/
entry/src/main/resources/rawfile/python/jieba_hnp_bridge.py
entry/src/main/resources/rawfile/python/jieba/ ← 打包进来的 jieba 源码与词典
各文件职责很清楚:
Index.ets:鸿蒙 PC 页面,负责输入 / 载入文本、选择操作、展示结果、导出;JiebaHnpClient.ets:ArkTS 业务封装,把分词操作变成 JSON 请求;JiebaHnpNative.ets:声明 Native 模块方法,并提供 TaskPool 并发函数;RawFileSync.ets:负责 rawfile 同步、URI 文件复制和沙箱文件读写;napi_init.cpp:通过 N-API 暴露runRequestJson(),并启动 HNP Python;jieba_hnp_bridge.py:真正 import jieba 并执行分词任务的 Python worker。
这里没有改写上游 jieba 源码,而是在外面加了一层鸿蒙 PC 调用壳。边界清晰:jieba 保持原有 Python 库形态,鸿蒙适配逻辑集中在 examples/harmony_pc/。

五、把 jieba 打包进 HAP:纯 Python 库的独特优势
这是这次适配里和别的 Python 三方库最不一样的地方。
因为 jieba 没有任何需要编译的扩展,我们可以把它的源码和词典直接放进应用资源里,随 HAP 一起分发。这样做的好处是:用户装好应用就能用,不依赖设备能不能联网、能不能 pip。
打包内容放在:
entry/src/main/resources/rawfile/python/jieba/
应用启动时 JiebaHnpClient.prepare() 会把整个 python/ 目录(含 jieba 包)同步到应用沙箱;Python worker 在 import jieba 前,把脚本所在目录插入 sys.path,于是命中的就是这份打包的 jieba:
def _ensure_bundled_jieba_on_path() -> None:
bridge_dir = os.path.dirname(os.path.abspath(__file__))
if bridge_dir not in sys.path:
sys.path.insert(0, bridge_dir)
为了控制体积(jieba 完整包含词典约 37MB),打包时排除了两类文件,最终约 18MB:
lac_small/:paddle 模式用的模型,本示例不启用,排除后省约 12MB;- 各模块的
*.p文件:jieba 仅在 Jython 上用它们,鸿蒙的 CPython 走.py版本,排除后再省约 7MB。
更新这份打包的 jieba(比如换版本)时,从仓库根目录重新同步即可:
cd /path/to/jieba
rm -rf examples/harmony_pc/entry/src/main/resources/rawfile/python/jieba
cp -R jieba examples/harmony_pc/entry/src/main/resources/rawfile/python/jieba
rm -rf examples/harmony_pc/entry/src/main/resources/rawfile/python/jieba/lac_small
find examples/harmony_pc/entry/src/main/resources/rawfile/python/jieba -name '*.p' -type f -delete
还有一个沙箱里的小细节:jieba 第一次加载会把词典缓存写成 jieba.cache。沙箱默认临时目录可能受限,所以 worker 通过环境变量 JIEBA_CACHE_DIR 把缓存指到应用沙箱里的可写目录,避免首次加载失败。
六、ArkTS 页面:从测试 demo 改成真实用户流程
页面拆成几个清楚的区域:输入文本、操作选择、参数、开始处理、处理结果、导出结果。
用户的真实使用顺序是:
- 在「输入文本」框直接输入 / 粘贴中文,或点「从文件载入」选择一个
.txt; - 在「操作」里选精确模式 / 全模式 / 搜索引擎 / 词性标注 / 关键词·TF-IDF / 关键词·TextRank;
- 分词类可切换「新词发现(HMM)」,关键词类可调「关键词数量」;
- 点「开始处理」,结果显示在下方;
- 点「导出结果」,通过保存选择器选择位置,把结果写成文本文件。
「从文件载入」和「导出结果」都走鸿蒙文件选择器,返回的是 URI。Python 三方库更习惯处理真实文件路径,所以这里统一按这个流程处理文件:
用户选择的文件 URI
-> RawFileSync.copyFile() 复制到应用沙箱
-> Python 读取沙箱文件
-> Python 写入沙箱输出
-> RawFileSync.copyFile() 复制到用户选择的保存 URI
页面不把内部沙箱路径暴露给用户,用户看到的是「已就绪」「正在处理」「处理完成」这类自然状态。

七、ArkTS Client:把分词操作变成 JSON 请求
JiebaHnpClient.ets 是应用侧调用 Python 的封装层。它不直接分词,而是组织请求、准备目录、调用 Native、解析返回值。页面只需要调用 cut()、tag()、keywords() 这几个方法。
比如精确分词会生成这样的 JSON 请求:
{
"op": "cut",
"text": "我来到北京清华大学,热爱自然语言处理和中文分词技术。",
"mode": "accurate",
"hmm": true,
"output": "/应用沙箱/outputs/xxx-result.txt"
}
关键词提取会生成:
{
"op": "keywords",
"text": "……",
"method": "tfidf",
"topK": 20
}
prepare() 负责建目录并把打包的 jieba 同步到沙箱。因为词典较大(约 18MB),同步只在每个会话里做一次,避免每次请求都重复复制。
八、Native/N-API:启动 HNP Python 进程
ArkTS 不能直接 import jieba,中间需要 Native/N-API 桥接。napi_init.cpp 暴露了 runRequestJson(pythonPath, bridgeScriptPath, requestJsonPath, workingDir),它拼出 HNP Python 启动命令并捕获 stdout。
这里和图像 / 科学计算类库有个明显区别:jieba 没有 NumPy / OpenBLAS 依赖,所以不会触发 SIGSYS(SYS_SECCOMP) 这类沙箱崩溃,Native 层也就不需要设置 OPENBLAS_NUM_THREADS 等一堆规避线程的环境变量。 命令很干净,核心就是:
cd <workingDir>
PYTHONDONTWRITEBYTECODE=1 JIEBA_CACHE_DIR=<workingDir>/jieba-cache \
<pythonPath> <bridgeScriptPath> --request <requestJsonPath> 2>&1
成功时返回 JSON(含 ok、词数、分词结果、预览文本等),失败时也返回 JSON(含错误类型、错误信息、traceback),方便页面展示。
九、Python bridge:真正调用 jieba
真正分词的是 jieba_hnp_bridge.py,它读取 JSON 请求,按 op 分发:
OPS = {
"demo": op_demo,
"cut": op_cut,
"tag": op_tag,
"keywords": op_keywords,
}
分词对应:
words = jieba.lcut(text, cut_all=False, HMM=hmm) # 精确模式
words = jieba.lcut(text, cut_all=True) # 全模式
words = jieba.lcut_for_search(text) # 搜索引擎模式
词性标注用 jieba.posseg,关键词提取用 jieba.analyse(TF-IDF 与 TextRank)。worker 最后把结果用 print(json.dumps(...)) 打到 stdout,Native 捕获后返回给 ArkTS。
十、真机调试踩的三个坑(这部分才是“实战”)
代码写完、能构建,不代表真机上就能用。把应用装到鸿蒙 PC 真机上点「开始处理」,我们连续踩了三个坑,逐个修好后才真正可用。
坑一:ModuleNotFoundError: No module named ‘jieba’
第一次真机运行,点「开始处理」后界面直接弹出红色「处理失败」,结果区是一段 Python traceback:
File ".../jieba-hnp/python/jieba_hnp_bridge.py", line 39, in <module>
import jieba
ModuleNotFoundError: No module named 'jieba'
原因很清楚:设备上的 HNP Python 没有装 jieba。这正好印证了前面那条铁律——HNP Python 环境里必须能 import 到这个库。
修复方式就是第五节讲的:既然 jieba 是纯 Python,干脆把它打包进 HAP,再在 import jieba 前把脚本目录插进 sys.path。改完之后,应用不依赖设备 pip,开箱即用。
坑二:界面弹出「应用无响应」(ANR)
打包 jieba 之后分词能跑了,但很快又遇到一个体验问题:连续点几次「开始处理」,系统弹出「jieba 分词没有响应 / 是否将其关闭?」。
原因是:Native 的 runRequestJson 内部用 popen 启动 HNP Python 并同步等待结果,而我们一开始是直接在 UI 线程调用它的。jieba 首次加载词典、Python 进程启动都要时间,UI 线程被卡住,系统就判定应用无响应。
修复方式是把这个同步调用放到 ArkTS 的 TaskPool 工作线程:
@Concurrent
export function runRequestConcurrent(
pythonPath: string, bridgeScriptPath: string,
requestJsonPath: string, workingDir: string): string {
const bridge = nativeBridge as JiebaHnpNativeBridge;
return bridge.runRequestJson(pythonPath, bridgeScriptPath, requestJsonPath, workingDir);
}
async runRequest(request, requestName): Promise<JiebaHnpCallResult> {
this.prepare();
const requestPath = this.writeRequestFile(requestName, request);
const raw = await taskpool.execute(
runRequestConcurrent, this.pythonPath,
this.paths.bridgeScriptPath, requestPath, this.paths.workDir) as string;
return JiebaHnpClient.toResult(raw);
}
这里有个 ArkTS 细节:
@Concurrent函数只能引用 import 变量或局部变量,不能直接用模块级派生常量,所以要在函数内部对导入的nativeBridge做一次本地类型转换。
改完之后,处理过程中界面会正常显示「正在处理」、控件变灰禁用,处理完恢复,不再卡死,也不再弹 ANR。
坑三:结果区出现一堆 SyntaxWarning,JSON 解析失败
异步修好后又发现:分词虽然成功(状态显示「处理完成」),但结果区显示的不是漂亮的分词结果,而是一堆:
.../jieba/__init__.py:44: SyntaxWarning: invalid escape sequence '\.'
re_han_default = re.compile("([一-...])", re.U)
...
原因有两层:jieba 0.42.1 是为较老的 Python 写的,它的正则字符串在新版 Python(3.12)上会触发 SyntaxWarning;而这些警告默认走 stderr,Native 层又用 2>&1 把 stderr 合并进了 stdout,于是警告被插在 JSON 前面,ArkTS 的 JSON.parse 直接失败、回退成显示原始文本。
这次从两端一起修(防御纵深):
- Python 侧:
import jieba前warnings.filterwarnings("ignore")屏蔽 SyntaxWarning,导入后logging.disable(logging.WARNING)关掉 jieba 的运行日志; - ArkTS 侧:解析输出时不假设整段都是 JSON,而是从后往前找出第一行能被解析成 JSON 的内容(worker 保证 JSON 是最后打印的一整行),任何前置噪声都不影响。
改完之后,输出是干净的单行 JSON,结果区正常显示分词结果。
十一、构建验证和真机测试
工程可以用 DevEco Studio 直接构建运行(推荐普通用户用这种方式:打开 examples/harmony_pc,连上鸿蒙 PC 真机,点运行)。第一次打开需要在 File > Project Structure > Signing Configs 里勾选「Automatically generate signature」完成自动签名。
也可以用命令行构建签名 HAP:
DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk \
/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw \
--mode module -p product=default -p module=entry@default \
assembleHap --no-daemon
构建成功会看到:
Finished :entry:default@CompileArkTS
Finished :entry:default@PackageHap
Finished :entry:default@SignHap
Finished :entry:assembleHap
BUILD SUCCESSFUL
装到真机并启动:
HDC=/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc
$HDC install -r entry/build/default/outputs/default/entry-default-signed.hap
$HDC shell aa start -a EntryAbility -b org.jieba.hnp.example
在鸿蒙 PC 真机(HarmonyOS 6.0.2 / API 22)上,下列功能都验证正常:
- 精确模式分词、全模式分词、搜索引擎分词;
- 词性标注;
- 关键词提取(TF-IDF、TextRank);
- 处理结果导出为文本文件;
- 处理过程中界面保持响应,不再出现「应用无响应」;
- 输出为干净 JSON(已屏蔽 SyntaxWarning 和运行日志)。
导出后,结果文件会写到用户在保存选择器里选择的位置,比如桌面或文档目录。

十二、这次适配的结果与方法论
完成后,这个示例已经不是一个验证按钮,而是一个接近真实使用场景的鸿蒙 PC 中文分词工具:
- 用户直接输入或从文件载入中文文本;
- 一个下拉框切换六种分词 / 标注 / 关键词能力;
- 结果可导出,导出走系统保存选择器;
- jieba 随应用打包,设备端不用 pip;
- 处理放在工作线程,界面不卡;
- 输出干净,不被库的日志 / 警告污染。
从这次适配可以总结出一套通用的 Python 三方库鸿蒙 PC 接入思路:
先在 HNP Python 中验证三方库
-> 再写 Python worker 承接 JSON 请求
-> 用 N-API 启动 Python 并捕获 stdout
-> 调用放到 TaskPool 工作线程,避免 UI 卡死
-> ArkTS Client 封装业务方法
-> ArkUI 页面走真实输入 / 文件选择 / 保存流程
-> 最后用真机和 DevEco 构建验证闭环
对 jieba 这种纯 Python 库,还可以额外把库本体打包进 HAP,省掉设备端安装。这条路线比重写底层算法更稳,也更容易推广到其他 Python 工具库(如 pandas、scikit-learn、requests 等)。如果要继续扩展,可以在这个基础上增加自定义词典、批量分词、TF-IDF/TextRank 参数调节、停用词管理等能力。
最后再强调一遍给最终用户的前置条件:在鸿蒙 PC 上使用这个软件前,请先到鸿蒙 PC 应用市场下载「Python 安装器」,用它把 Python 环境装好,应用才能正常调用 HNP Python 完成分词。
更多推荐





所有评论(0)