在Windows 10上装HanLP说难不算难说容易也真不算容易。我头一回折腾这个开源中文自然语言处理工具包就在版本选择上栽了跟头——装完pyhanlp跑起来报JVM找不到换成hanlp又因为模型下载卡了半小时。后来把两代HanLP的差异、Windows特有的环境坑都摸了一遍才算真正跑顺。这篇文章就把我在Windows 10上配置和使用HanLP的全过程、踩过的坑和验证过的方案记录下来给同样想在本机跑中文分词、词性标注、命名实体识别、依存句法分析的人一份可以直接照着做的参考。1. 版本选择是第一道分水岭1.x和2.x的差别直接决定你装哪个1.1 两个大版本的底层差异HanLP从1.x到2.x不是简单的小版本升级而是底层架构重写。1.x时代的Python包叫pyhanlp本质是通过JPype把Java的HanLP库包了一层壳。所以装pyhanlp之前必须先装好Java的JDK否则运行时会直接报JVM相关错误。而2.x的hanlp包则完全用Python实现底层依赖PyTorch这类深度学习框架不需要Java但模型体积和内存占用明显更大。把两个版本的关键差异列成一张表看着最直观对比项pyhanlp1.xhanlp2.xPython包名pyhanlphanlp是否依赖Java依赖需JDK 8不依赖底层实现通过JPype调用Java纯Python PyTorch预训练模型以传统统计模型为主深度学习模型支持微调覆盖任务分词、词性标注、NER、依存句法等分词、词性、NER、依存/语义依存、文本分类、相似度、语义角色标注等模型体积较小通常在几百MB内较大单模型从几十MB到数GB不等适合场景轻量应用、教学、快速原型生产环境、追求效果的深度学习项目1.2 我最终怎么选的我的建议分两种情况。如果你的需求就是经典NLP四件套——分词、词性标注、命名实体识别、依存句法分析而且机器配置一般那pyhanlp更顺手。模型加载快、启动时间短、接口直接写教学代码和快速验证都很方便。如果你要做更复杂的任务比如语义角色标注、文本相似度、情感分析或者你本来就在用PyTorch做深度学习项目那直接上2.xAPI风格统一和你的技术栈也匹配。这里有个反直觉的坑很多人觉得2.x一定比1.x好用结果装上2.x之后发现一个中文分词模型动辄几百MB第一次加载慢得离谱就回头抱怨。其实不是2.x不好是选型没匹配上场景。我在实际项目里是两个版本都装了但放在不同的虚拟环境里隔离使用互不干扰具体做法下一节讲。注意pyhanlp和hanlp包名非常相似混装在同一环境里容易互相污染依赖关系强烈建议用虚拟环境分开。2. Windows 10环境准备JDK、Python和网络加速2.1 JDK安装与环境变量配置如果选pyhanlp第一步是装JDK。Windows 10下装JDK最常见的错误是装完Java后没配置JAVA_HOME和PATH导致运行时找不到Java环境。JDK版本我建议用JDK 8或11太新的版本在个别场景下会和JPype的旧版本冲突。配置步骤如下安装JDK注意安装路径不要带中文和空格比如统一放到C:\jdk8。右键“此电脑” → 属性 → 高级系统设置 → 环境变量。新建系统变量JAVA_HOME值填C:\jdk8。在系统变量Path中新增%JAVA_HOME%\bin。打开新的命令行窗口输入java -version验证能看到版本信息就表示配置成功。这一步看着简单但我在给别的机器配置时遇到过一种隐蔽问题装了JDK 17命令行java -version都正常但pyhanlp一跑就报错。排查下来是JPype版本太老不支持高版本JDK的某些内部接口。解决办法有两个要么装回JDK 8要么升级pyhanlp。优先建议前者因为1.x生态本来就偏好在Java 8上运行。2.2 Python版本与虚拟环境隔离Python版本方面pyhanlp对Python 3.8、3.9兼容性最好hanlp2.x要求Python 3.8我实测3.9和3.10都能稳定运行3.11在某些依赖上会有编译问题所以不建议追新。我习惯用conda创建环境conda create -n hanlp18 python3.9 conda activate hanlp18不想装conda的话用venv也行python -m venv D:\envs\hanlp18 D:\envs\hanlp18\Scripts\activate注意Windows下venv的激活脚本在Scripts目录不是bin目录第一次用venv的人经常在这里卡住。另外如果你系统里装了多个Python版本最好用python -m venv而不是直接敲venv命令否则容易调错解释器。2.3 pip镜像与模型下载加速Windows 10下pip默认源在国外安装依赖时经常超时。我在命令行里先配一个国内镜像pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple这个命令在Windows 10上会写入用户目录下的pip.ini之后所有pip安装都走镜像一劳永逸。换源之后装pyhanlp、torch这类大包的速度差距非常明显。模型下载是另一个容易卡住的环节。HanLP 2.x首次使用会在用户目录下创建hanlp相关目录然后从远程下载模型文件。如果下载中断再次使用会尝试继续。但不方便访问官方源的话也可以手动下载模型后放进缓存目录Windows下通常是C:\Users\你的用户名\hanlp。放置规则是“模型打包名/模型文件名”我习惯把整个解压后的模型目录放进去让HanLP按名称自动寻找。3. 安装实战从pip安装到跑出第一个分词结果3.1 pyhanlp的完整安装过程在虚拟环境里执行pip install pyhanlp安装过程本身很快真正耗时的是第一次import。pyhanlp在首次调用时会自动下载HanLP的Java工包和data数据包网络不好时很容易卡在下载阶段。我的经验是如果进度条长时间不动先停掉检查用户目录下的.hanlp目录里面有个文件锁。上次下载没正常结束时锁文件会残留需要删掉再重新尝试。首次运行验证代码新建一个test.pyfrom pyhanlp import * print(HanLP.segment(自然语言处理是人工智能的重要方向))如果控制台输出类似[自然语言/nz, 处理/v, 是/v, 人工智能/nz, 的/uj, 重要/a, 方向/n]的结果说明基础环境已经通了。这里的/nz、/v就是词性标注/uj是助词。实际观察能发现pyhanlp把“自然语言”“人工智能”整体识别出来了而不是拆成“自然/语言/处理”这正是中文分词器的价值所在。3.2 hanlp 2.x的完整安装过程2.x的安装稍微重一些因为依赖PyTorchpip install hanlp pip install torch --index-url https://download.pytorch.org/whl/cpu第二行是刻意的做法如果机器没有独立显卡装CPU版PyTorch体积小、安装快做实验和基本开发完全够用。有NVIDIA显卡且配好CUDA的可以装GPU版推理快一些但CPU版对大多数人来说已经够了。装完写个最简单的调用import hanlp tokenizer hanlp.load(hanlp.pretrained.tok.COARSE_ELECTRA_SMALL_ZH) print(tokenizer(这家店的商品质量很不错))第一次运行会输出模型下载日志然后在用户目录生成缓存。跑通之后你会注意到2.x的调用方式是先加载模型得到一个可调用对象再用这个对象处理文本和1.x那种全局HanLP接口风格明显不同。这种设计的好处是你可以同时加载多个模型自由组合成pipeline后面会演示。3.3 安装成功的判断标准和测试陷阱经常有人问“装完了怎么判断装好没”。我的标准很简单跑一个最小demo输出符合预期就算通。但这里有个测试陷阱——不要一上来就加载最大的模型比如ELECTRA的大型中文版本加载就要几分钟很容易让人误以为程序卡死了。最小验证应该用轻量模型2.x就用COARSE_ELECTRA_SMALL_ZH1.x就直接用默认分词。另外建议把测试文本控制在20个字以内既能验证效果又不必等太久的处理时间。等确认整体流程通了再上长文本和大模型。4. 核心功能实操分词、词性标注、NER和依存句法4.1 一段代码跑通四个经典任务安装不是目的用起来才是。这一节给出一套可以直接抄的完整示例覆盖四个最常见任务。先看pyhanlp版本from pyhanlp import * # 标准分词 print(HanLP.segment(自然语言处理是人工智能的重要方向)) # 词性标注 sentence 我爱自然语言处理技术 for term in HanLP.segment(sentence): print(f{term.word} - {term.nature}) # 命名实体识别 print(HanLP.ner(张三在某科技公司担任算法工程师家住江东市湖新区)) # 依存句法分析 print(HanLP.parseDependency(张三在某科技公司任职))pyhanlp的接口命名很直白segment是分词加词性标注一步到位ner输出实体标记parseDependency输出依存关系树。需要注意的是pyhanlp默认NER模型对“张三”这种两字人名有时识别不出这是模型训练数据决定的不一定是Bug。解决方式是结合自定义词典兜底或者换2.x的深度学习NER模型后者对人名的识别能力强很多。再来看hanlp2.x版本因为需要模型组合代码会多几行import hanlp text 张三在某科技公司担任算法工程师家住江东市湖新区 # 分词 tokenizer hanlp.load(hanlp.pretrained.tok.COARSE_ELECTRA_SMALL_ZH) tokens tokenizer(text) print(tokens) # 词性标注 pos_tagger hanlp.load(hanlp.pretrained.pos.CTB5_POS_RNN_FAST_ZH) print(pos_tagger(tokens)) # 命名实体识别 ner hanlp.load(hanlp.pretrained.ner.MSRA_NER_ELECTRA_SMALL_ZH) print(ner(tokens)) # 依存句法分析 parser hanlp.load(hanlp.pretrained.dep.CTB7_BIAFFINE_DEP_ZH) print(parser(tokens))这个例子演示了一个关键习惯在2.x里分词结果可以作为下游任务的输入而不是每次都传原始文本。这既避免重复计算也让每个模型各司其职——分词器只管切词NER只管识别实体职责清晰。4.2 自定义词典解决领域分词不准的通用手段分词器再强也扛不住专业领域词汇。比如“冷链物流”这类词通用模型可能拆成“冷链/物流”如果你的业务要求它作为一个整体就需要自定义词典。pyhanlp的自定义词典很简单from pyhanlp import * CustomDictionary.add(冷链物流) print(HanLP.segment(冷链物流行业报告发布))2.x的自定义词典稍微绕一点。如果只是个别词可以在分词结果上做后处理合并tokens tokenizer(冷链物流行业报告发布) merged hanlp.utils.rules.merge_spans(tokens, [冷链物流]) print(merged)如果你有一整份领域词表更推荐把词表写进文件再批量加载。pyhanlp的做法是编辑用户目录下的CustomDictionary.txt一行一个词2.x的做法是在加载分词器时配置词典参数。批量处理词典时我建议先做清洗去掉重复词、去掉长度小于2的词、去掉明显是噪声的行能明显提升最终效果。4.3 停用词过滤与文件编码问题分词之后通常要做停用词过滤。很多初学者问HanLP有没有内置停用词表答案是没有需要自己准备。我一般用一个几百行的停用词表把“的、了、和、是、在”这类高频无意义词过滤掉。实用代码片段stopwords set() with open(stopwords.txt, r, encodingutf-8) as f: for line in f: stopwords.add(line.strip()) tokens HanLP.segment(这家店的商品质量很不错) filtered [t.word for t in tokens if t.word not in stopwords and t.word.strip()] print(filtered)注意读取停用词文件时必须显式指定utf-8编码。Windows的记事本默认可能用GBK保存文件如果文件编码和读取编码不一致轻则乱码重则直接抛异常。这个坑在Windows上出现频率极高我每次写文件读写代码都会下意识检查编码参数。4.4 批量文本处理与性能实测实际项目里不会只处理一句话而是灌入成千上万条文本。pyhanlp本身不是线程安全的多线程并发调用同一个JVM实例会出现不可预期的问题。我实测过在Windows 10上跑10万条短文本分词单线程大约3分钟左右尝试多线程不仅没加速反而因为GIL和JVM交互出现性能下降。所以pyhanlp的正确批量姿势是单线程顺序处理或者用multiprocessing开多个进程每个进程一个独立的JVM实例。2.x在CPU版PyTorch下可以充分利用矩阵计算。它支持直接传列表texts [第一条测试文本, 第二条测试文本, 第三条测试文本] print(tokenizer(texts))实测同样10万条短文本2.x的CPU推理大约比pyhanlp快20%到30%但前提是批大小合理一般32到64比较合适太大反而因为内存占用过高拖慢速度。如果你处理的是长文本批大小要相应调小否则单条长度会撑爆模型的最大序列长度。5. Windows 10上的坑位地图编码、路径、内存和兼容性5.1 控制台编码GBK与UTF-8的拉锯战Windows 10自带命令行工具默认代码页是GBK而HanLP输出的是UTF-8文本。常见表现是在IDE里运行正常一换到cmd窗口就报UnicodeEncodeError: gbk codec cant encode character。有两个解决办法。第一个最直接在Python脚本开头加两行import sys sys.stdout.reconfigure(encodingutf-8)第二个是在“设置 → 时间和语言 → 语言 → 管理语言设置 → 更改系统区域设置”里勾选“Beta版使用Unicode UTF-8提供全球语言支持”然后重启电脑。这个方案一劳永逸但会让一些老软件显示乱码能不能接受取决于你的使用场景。我个人更推荐第一种只影响当前脚本不影响整个系统。写文件时也有同样的坑用open函数写含中文的结果文件如果不指定encodingutf-8Windows默认按GBK写文件再被其他程序读取就乱码了。所以只要涉及读写文本一律显式指定encodingutf-8这是Windows上最值得养成的习惯之一。5.2 路径分隔符与中文路径的坑Windows 10的路径用反斜杠而HanLP的模型配置和数据路径在很多地方是正斜杠风格。混合使用容易出问题。我踩过的典型坑是用代码指定模型路径时写成data\model\xxx结果反斜杠在Python字符串里被当成转义字符反而报文件找不到。正确做法是使用原始字符串或统一正斜杠model_path rD:\hanlp_data\model # 或者 model_path D:/hanlp_data/model另一个坑是中文路径。HanLP对中文路径的支持在Windows上时好时坏特别是pyhanlp的Java端有概率出现读取不到数据的诡异问题。我的建议是所有涉及HanLP的目录一律用纯英文路径不要放在“桌面”“文档”这种中文路径下宁可目录名丑一点也要保证稳定。这个建议在我处理过的几乎所有Windows NLP环境里都适用。5.3 内存和JVM参数调整pyhanlp在Windows上运行JVM默认堆内存可能不够用处理长文本时偶尔会出现OutOfMemoryError。可以通过设置JVM参数来调整import pyhanlp pyhanlp.HANLP_JVM_OPTIONS -Xms512m -Xmx2048m但注意这个设置必须在JVM第一次启动之前完成JVM一旦启动再设置就无效了。保险的做法是直接在系统环境变量里加一条HANLP_JVM_OPTIONS-Xms512m -Xmx2048m这样无论从哪里启动Python都能生效。2.x的内存问题集中在PyTorch模型上。加载大模型比如ELECTRA_LARGE中文模型需要2GB以上内存在8GB内存的老机器上会跑得很紧张。建议先看模型体积再决定是否加载同时留意任务管理器里的内存占用。我在一台16GB内存的机器上同时加载分词、NER、依存句法三个中等模型内存峰值大概在5GB左右供你参考。5.4 高频报错速查表把我在Windows 10上频繁遇到的报错整理成速查表遇到问题直接对号入座报错信息原因解决方案JVMNotFoundException / NoClassDefFoundError未装JDK或JAVA_HOME未配置装JDK 8并配置环境变量UnicodeEncodeError: gbk codec控制台编码不是UTF-8stdout重配utf-8或改系统区域设置FileNotFoundError: data/model/xxx路径分隔符或路径写错用正斜杠或原始字符串确认路径存在OutOfMemoryError: Java heap spaceJVM堆内存不足调大-Xmx参数AttributeError: module hanlp has no attribute pretrainedhanlp版本过旧或装错包pip install -U hanlp升级模型下载卡住或超时网络源访问慢手动下载模型放入缓存目录TypeError: NoneType object is not callable模型未加载成功检查模型缓存目录和磁盘空间这张表我每次帮别人排查问题时都直接发基本能覆盖八成情况。剩下两成大多属于环境太特殊比如系统里装了多个Python版本导致pip装错环境这种时候先执行pip show pyhanlp或pip show hanlp看包实际装在了哪里再逐项排查。6. 沉淀下来的几条实操经验最后分享几个我反复使用的技巧。第一无论用哪个版本我都把模型初始化放在进程启动阶段而不是每次请求都加载模型加载一次的成本可能比处理几百条文本还高。第二处理大规模语料时我会先小批量测试流程跑通再上全量数据避免跑到一半才发现输出编码有问题返工成本很高。第三HanLP在Windows 10上整体稳定适合做开发调试但如果要部署到生产环境或做多进程服务建议放到Linux容器里跑Windows 10更适合作为日常开发和验证环境。如果你刚被版本选择弄得晕头转向或者在各种报错信息里挣扎希望这份记录能帮你少走点弯路。我自己就是从“装不上、跑不通”一路试过来的把版本选对、环境配好、编码处理妥当之后HanLP在Windows 10上其实相当省心。
阅读完成 · 觉得有帮助?