你是否遇到过这种情况:
跟着教程安装了一堆 Python 库,结果某个库版本冲突,程序在本地跑得好好的,到了同事电脑上直接报错;今天要用 TensorFlow,明天要跑一个老项目,可项目用的还是 Python 3.6,你已经在用 3.11,结果所有包挤在一个环境里,互相打架;更常见的是——你打开 Jupyter Notebook,明明刚才在终端里pip install装好了jieba,进 Notebook 一import jieba,却提示 ModuleNotFoundError。
这不是你操作有问题,而是你根本没有把“Python 环境”和“Jupyter Notebook 内核”的关系理顺。
这篇是环境搭建系列的第二部分(P2)。上一篇讲过 Python 和基础工具的准备工作,这一篇我们聚焦两件事:一是用 Virtual Env 为 NLP 项目创建干净独立的 Python 环境;二是让 Jupyter Notebook 正确使用这个虚拟环境,完成关键词提取全流程。
文章里会涉及 Jupyter Notebook 和 Jupyter Lab 的区别、虚拟环境与内核的关系、NLP 关键词提取的完整代码示例,以及常见的 Google Colab 之外的本地环境坑。如果你正打算用 Python 做 NLP、文本挖掘、关键词提取这类项目,这篇文章建议收藏备用。
1. 这篇文章真正要解决的问题
先说一个反直觉的事实:很多新手甚至工作两年以上的开发者,对“虚拟环境”的理解依然停留在“因为教程这么说”的阶段。
于是你会在真实项目里反复看到这些场景:
第一,全局环境被污染。pip install装了一堆包,今天装numpy,明天装transformers,后天发现某个项目要求的numpy==1.19和你要用的numpy==1.24必须同时存在,冲突无法解决。
第二,Jupyter 里的环境不是你以为的环境。有人在终端里用conda activate myenv激活了某个环境,然后启动 Notebook,发现import的包仍然是另一个环境的。因为 Jupyter Notebook 通过“内核”(kernel)来执行代码,内核指向哪个 Python,Notebook 就使用哪个环境,和你终端里激活了哪个环境没有必然关系。
第三,NLP 项目是环境依赖最敏感的项目类型之一。jieba、nltk、scikit-learn、transformers这些库对 Python 版本和彼此的版本约束非常敏感。比如旧版的sklearn和新版接口完全不一样,nltk的数据下载路径、transformers对tokenizers的依赖,一不小心就全盘崩溃。
这篇文章要帮你解决的核心痛点就是:
- 为每个 NLP 项目创建独立的 Python 虚拟环境,隔离依赖;
- 把这个虚拟环境注册为 Jupyter Notebook 的内核,让 Notebook 能用对环境;
- 用一个关键词提取的完整示例,把从环境到模型的整条链路跑通。
适合读者:正在学习 NLP、文本挖掘、搜索引擎相关技术的开发者;做数据分析和文本处理、想规范化本机环境的工程师;以及每次打开 Jupyter 都因为环境问题浪费半天时间的同学。
2. Jupyter Notebook、虚拟环境与内核的关系
这个部分属于基础但关键,务必搞清楚。很多人卡在环境问题上,就是因为这三个概念其实是三层东西。
2.1 三个概念的定义
Jupyter Notebook是一个基于 Web 的交互式开发环境,它以.ipynb文件为载体,支持代码、Markdown、公式、图表混排。它对 NLP 这类探索式分析特别友好——你可以在一个单元格里写完分词,立刻在下一个单元格里看结果,再下一个单元格做可视化。
Jupyter Lab是 Notebook 的下一代界面,同一窗口里可以并排打开 Notebook、终端、文件管理器,更接近一个“Web IDE”。两者的内核机制完全相同,本篇写完的配置对 Lab 同样有效。
Python 虚拟环境(Virtual Env)是一个独立的 Python 运行目录,里面有自己的site-packages包目录,可以理解为给项目单独开了一个“厨房”,互不干扰。最常见的工具是 Python 自带的venv和 Anaconda 的conda create。
2.2 内核才是 Notebook 的执行引擎
关键来了:Jupyter Notebook 本身不执行 Python 代码。你在单元格里写的代码,是发给后台的 “kernel” 去执行的。这个 kernel 是一个独立的 Python 进程,它使用哪个 Python 解释器、哪个包目录,取决于你启动 kernel 时用的环境。
所以你会发现:
- 你在终端里
conda activate myenv后pip install jieba - 然后你在另一个终端启动
jupyter notebook - 打开 Notebook 后,右上角显示的内核是
Python 3,用的是 base 环境 import jieba失败
为什么?因为 Notebook 关联的内核是 base Python,你的jieba装在myenv里,两者根本不认识。这就是最大的认知偏差。
2.3 一个类比帮助理解
把 Jupyter Notebook 当成一个“遥控器”,它会向后台的“播放器”发送指令。内核就是那个播放器,它的底层是某个特定的 Python 环境。
你换了个地方装了一堆新歌(安装包),但是遥控器对应的播放器还是原来那个,自然放不出新歌。要让新歌能放,要么换一个支持新歌的播放器(切换内核),要么让原来的播放器也连上你的新歌库(把包装进当前内核的环境)。
从这个角度就能理解 Jupyter 生态里最常用的一个操作:把虚拟环境注册为内核。
3. 环境准备与前置条件
开始动手之前,先明确本文演示的环境假设。
- 操作系统:Windows / macOS / Linux 都可以,命令略有区别
- Python 版本:推荐 3.8 及以上;具体版本以你实际安装为准,本文不绑定某个特定版本
- 工具选择:本文以
conda为例,同时给出python -m venv的对应命令 - 包管理器:
pip(如果你用 conda 也可以,但pip install更通用)
如果你没有安装 Anaconda,建议优先安装 Anaconda,因为它自带 Python、Jupyter、常用数据科学包,对新手上手最友好。如果你更喜欢原生 Python,也可以直接装官方 Python,然后手动安装 jupyterlab。
另外强调一个判断:Notebook 和 Lab 不是二选一,大多数情况下环境一样,界面不同。对于 NLP 开发,我更推荐 Lab,因为它能同时开多个 Notebook、终端和文件面板,调试效率更高。但如果你已经习惯了 Notebook,可以继续用,本篇所有配置完全通用。
安装完成后,在终端里验证:
python --version jupyter --version conda --version # 如果你使用 Anaconda / Miniconda能正常输出版本信息,就说明基础环境 OK。
4. 创建 Python 虚拟环境并安装依赖
4.1 选择虚拟环境工具:venv 还是 conda
先给结论:
- 如果只是做 NLP 这类偏数据科学的项目,用
conda create更方便,因为 conda 能锁 Python 版本,还能管理部分非 Python 依赖。 - 如果已经在用官方 Python,不想装 Anaconda,那就用
python -m venv,轻量干净。
更稳妥的习惯是:一个项目一个环境,不要所有项目用同一个环境。这句话值得多强调几遍,因为绝大多数新手栽过的坑,就是所有项目共用 base 环境。
4.2 用 conda 创建环境
conda create -n nlp-env python=3.9 -y conda activate nlp-env其中nlp-env是环境名称,可以自己改。python=3.9可以改成你需要的版本号。
4.3 用 venv 创建环境
mkdir nlp_project cd nlp_project python -m venv venvWindows 激活:
venv\Scripts\activatemacOS / Linux 激活:
source venv/bin/activate激活后终端提示符前会多一个(venv)或(nlp-env),说明当前终端已经进入该虚拟环境。
4.4 安装 NLP 与 Jupyter 相关依赖
激活环境后,在环境内安装依赖:
pip install --upgrade pip pip install jupyterlab pip install jieba scikit-learn pandas如果要做更完整的 NLP 实验,可以追加:
pip install nltk pip install gensim这里jieba是中文分词库,scikit-learn用于 TF-IDF 特征计算和关键词排序,pandas做数据处理,jupyterlab是本篇要用的交互界面。
注意:这里安装的包只属于 nlp-env 这个环境,不会污染全局环境。这就是虚拟环境的隔离价值。
5. 在 Jupyter Notebook 中注册虚拟环境内核
环境创建好、依赖装好后,很多人的下一步是直接敲jupyter lab。结果打开 Notebook,发现内核名称还是Python 3,用的是 base 环境。
这就回到了第 2 节说的核心概念。要解决这个问题,需要把刚才创建的环境注册成 Jupyter 的内核。
5.1 安装 ipykernel
激活目标环境后,先安装ipykernel:
conda activate nlp-env pip install ipykernel5.2 注册内核
python -m ipykernel install --user --name nlp-env --display-name "NLP Env"命令解释:
--user:给当前用户注册内核,避免权限问题--name:内核的内部名称,建议和虚拟环境名一致--display-name:在 Jupyter 界面上显示的名称,可以写成方便识别的中文或英文
执行成功后,终端会输出:
Installed kernelspec nlp-env in /Users/xxx/Library/Jupyter/kernels/nlp-env看到这行说明注册成功。
5.3 验证内核是否生效
启动 Jupyter Lab:
jupyter lab在界面右上角点击内核名称(默认是Python 3),选择刚才注册的NLP Env。然后在第一个单元格里执行:
import sys print(sys.executable)如果输出路径中包含nlp-env,说明 Notebook 当前使用的 Python 就是你的虚拟环境,环境隔离成功。
很多教程到这里就结束了,但实际开发中还远远不够,因为真正考验一个环境好不好用,是它跑不跑得通完整的 NLP 流程。
6. NLP 关键词提取完整示例
关键词提取是 NLP 里最常见的基础任务之一,广泛应用于 SEO 文章分析、新闻主题识别、舆情监控、推荐系统标签生成。它的核心目标是从一段文本中自动找出最能代表主旨的词语。
这里我们实现一个经典方案:jieba 分词 + TF-IDF 关键词提取。
TF-IDF 是一个统计学方法,核心思想是:
- TF(词频)衡量一个词在本文档中出现的次数,次数越高越重要;
- IDF(逆文档频率)衡量一个词在所有文档中的区分能力,越冷门但越能代表文档的词,IDF 越大;
- 两者相乘,得到单词的权重,权重越高越可能是关键词。
6.1 完整代码
在 Jupyter Notebook 的新单元格中创建如下代码。建议先在一个新文件中编写,保存为keyword_extraction.py,再逐步在 Notebook 中改写成单元格形式,便于理解。
# -*- coding: utf-8 -*- """ 基于 jieba + scikit-learn 的 TF-IDF 关键词提取示例 运行前提:已经激活 nlp-env 虚拟环境,并安装了 jieba / scikit-learn """ import jieba import jieba.analyse from sklearn.feature_extraction.text import TfidfVectorizer # 1. 准备待分析的文本 text = """ Python 是一门非常流行的编程语言,在人工智能、数据分析和自然语言处理领域应用广泛。 自然语言处理是人工智能的一个重要方向,它研究如何让计算机理解、处理和生成人类语言。 关键词提取是自然语言处理中的基础任务,它可以从一段文本中自动找出重要的词语。 这篇文章主要介绍如何利用 Python 搭建自然语言处理环境,并进行关键词提取。 虚拟环境可以帮助开发者隔离不同项目的依赖,避免版本冲突。 Jupyter Notebook 是数据科学领域非常流行的交互式开发工具,它支持代码、文档和可视化的一体化操作。 """ # 2. 方案一:jieba 自带 TF-IDF 关键词提取 print("===== 方案一:jieba.analyse.extract_tags =====") tags = jieba.analyse.extract_tags(text, topK=10, withWeight=True) for word, weight in tags: print(f"{word}\t{weight:.4f}") print() # 3. 方案二:自定义 TF-IDF 向量化提取关键词 print("===== 方案二:scikit-learn TfidfVectorizer =====") def get_tfidf_keywords(text, topK=10): """使用 TfidfVectorizer 提取关键词""" # 先用 jieba 对文本进行分词,再用空格连接 words = jieba.lcut(text) # 过滤掉单个字符和空字符,保留长度大于1的词 words = [w.strip() for w in words if len(w.strip()) > 0] word_str = " ".join(words) # 创建 TF-IDF 向量器 vectorizer = TfidfVectorizer( token_pattern=r"(?u)\b\w+\b", # 用正则匹配词语 max_features=1000 # 最多提取 1000 个特征 ) # 注意:TfidfVectorizer 需要传入一个文档集合(列表), # 这里把单个文本作为唯一文档 tfidf_matrix = vectorizer.fit_transform([word_str]) # 获取特征词列表 feature_names = vectorizer.get_feature_names_out() # 获取每个词的 TF-IDF 权重 # todense() 将稀疏矩阵转换为稠密矩阵 weights = tfidf_matrix.toarray().flatten() # 组合成 (词, 权重) 列表,并按权重降序排列 word_weights = list(zip(feature_names, weights)) word_weights.sort(key=lambda x: x[1], reverse=True) return word_weights[:topK] keywords = get_tfidf_keywords(text, topK=10) print("词/权重结果:") for word, weight in keywords: print(f"{word}\t{weight:.4f}")6.2 代码核心逻辑说明
这段代码包含两层价值:
第一,jieba.analyse.extract_tags是最省事的方案,两行代码直接得到关键词和权重。它的内部实现也基于 TF-IDF 思路,同时附带了一些停用词过滤和词性筛选,适合快速实验。
第二,TfidfVectorizer是更“工业化”的方案。当你需要自定义语料库、自定义停用词表、或者把 TF-IDF 特征喂给下游模型时,就得用这种写法。TfidfVectorizer返回的是一个稀疏矩阵,实际项目里文档量可能百万级,一定不要转换成稠密矩阵直接存内存,否则内存很容易爆掉。这里为了演示单文档结果才用toarray()。
真正容易踩坑的地方在于:TfidfVectorizer默认期望的输入是字符串列表,每个字符串是一个文档。如果你传入的是原始中文文本而没有分词,效果会很差,因为英文分词靠空格天然完成,而中文分词必须显式调用jieba完成。
6.3 如何运行
如果你在终端运行整个脚本:
conda activate nlp-env python keyword_extraction.py如果你在 Jupyter Notebook 中演示,则把代码拆成几个单元格:
- 第一个单元格:导入库 + 定义文本
- 第二个单元格:jieba 方案
- 第三个单元格:TF-IDF 方案
这样做的好处是,你可以单独看每步的输出,方便排查。
7. 运行结果与效果验证
7.1 预期输出
如果环境配置正确、代码运行成功,你会在终端或 Notebook 单元格下方看到类似如下输出:
===== 方案一:jieba.analyse.extract_tags ===== 自然语言处理 0.3184 关键词提取 0.2632 文本 0.1662 Python 0.1371 虚拟环境 0.1210 开发者 0.1082 ... ===== 方案二:scikit-learn TfidfVectorizer ===== 词/权重结果: 自然语言处理 0.4865 关键词提取 0.4123 Python 0.3652 ...数值不必完全一致,因为权重会受分词结果和版本影响,但有几个判断标准:
自然语言处理、关键词提取这类领域核心词应该排在前列;的、了、是这类停用词不应该出现在结果前列;- 两个方案返回的关键词应该有较大重合,但权重不同。
如果结果里全都是“的”“了”“是”这类词,说明停用词过滤没做好,需要在分词后添加自定义停用词表。
7.2 如何判断环境是否成功
运行关键词提取本身只是验证模型,但要确认你是用 nlp-env 跑出来的,可以单开一个单元格执行:
import jieba print(jieba.__file__)如果输出路径包含nlp-env,例如:
/Users/xxx/anaconda3/envs/nlp-env/lib/python3.9/site-packages/jieba/__init__.py说明 Jupyter 内核已经指向虚拟环境,所有包从虚拟环境加载。如果路径是 base 环境或系统 Python,说明内核切换失败,回到第 5 节重新检查。
7.3 失败时的第一步排查顺序
- 先执行
import sys; print(sys.executable),确认内核指向哪个 Python - 再执行
pip list,看目标包里有没有 jieba / scikit-learn - 然后
pip show jieba,看包安装在哪个路径 - 最后检查 ipykernel 是否注册到了正确的环境
大多数内核不生效的问题,都出在这四步中的某一步。
8. 常见问题与排查思路
下面这张表是大量本地环境问题的高度浓缩,建议直接收藏。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Jupyter Notebook 页面空白 | 浏览器缓存、Jupyter 版本问题、端口冲突 | 查看终端日志;换浏览器;清理浏览器缓存 | 升级jupyterlab;尝试jupyter notebook --no-browser;换端口启动 |
| 在终端激活了虚拟环境,但在 Notebook 里 import 报错 | 内核没有指向虚拟环境,Notebook 使用 base 内核 | 在 Notebook 里执行sys.executable看路径 | 用ipykernel将虚拟环境注册为内核,并在 Notebook 中切换内核 |
| 已经切换内核,但 import 的包版本不对 | 同一个包在虚拟环境和 base 环境都有安装,内核切换后解释器与包路径不一致 | pip show 包名查看路径 | 确保激活环境后重新安装依赖;可在 Notebook 中手动sys.path.insert或使用pip --user定位 |
安装包时报ERROR: Could not find a version that satisfies the requirement | Python 版本过高或过低,包不支持 | 查看包官方支持的 Python 版本范围 | 创建环境时指定合适的 Python 版本 |
pip install很慢或超时 | 默认源访问慢 | 查看 pip 日志 | 配置国内镜像源,如清华源、阿里源 |
Windows 下activate命令不生效 | 激活命令输错,或使用了 PowerShell 与 CMD 混用 | 检查终端类型,确认路径分隔符 | Windows CMD 用venv\Scripts\activate.bat,PowerShell 用venv\Scripts\Activate.ps1 |
| 启动 Jupyter 后找不到刚注册的环境 | 注册时使用的 Python 与启动 Jupyter 的 Python 不一致 | 在终端执行which python/where python | 确保在目标环境内安装 ipykernel 并注册 |
TfidfVectorizer报empty vocabulary | 文本分词后所有词都被过滤 | 检查停用词表,确认 token_pattern 匹配中文 | 用 jieba 分词后再构造文档字符串 |
每个环境下问题细节会有差异,但排查思路是一致的:先定位内核路径,再定位包路径,最后对比版本。不要一上来就重装整个 Conda,那是最后手段。
9. 最佳实践与工程建议
走到这一步,环境已经能为你的 NLP 项目服务了。这里再补充几条工程上非常实用的建议,帮助你避免从“能跑”到“好维护”之间的坑。
9.1 一个项目一个环境,环境命名要规范
建议环境名和项目名保持一致,比如项目叫news_classification,环境名就叫news-classification-env。这样你电脑上环境多了以后,不会出现“昨天建的环境叫什么来着”的尴尬。
9.2 使用 requirements.txt 锁定依赖
当项目可以正常运行后,在项目根目录导出依赖清单:
pip freeze > requirements.txt其他人拿到项目后,创建新环境并安装依赖:
conda create -n new-env python=3.9 -y conda activate new-env pip install -r requirements.txt这比你让同事一个个pip install要可靠得多。对于 NLP 项目,requirements.txt还能记录 jieba、nltk、scikit-learn 的精确版本,避免“我这能跑你那跑不了”。
9.3 不要什么都往 base 环境里装
Anaconda 安装后自带一个base环境,很多人图省事,直接conda install/pip install往里装包。短时间很爽,时间长了 base 环境就会变成“垃圾场”,依赖冲突的概率指数上升。
更稳妥的做法是:base 环境只用于 conda 和 jupyter 的基础启动,项目依赖全部放在各自的虚拟环境里。
9.4 大模型与预训练模型依赖要单独处理
如果你后续要跑 BERT、GPT 这类预训练模型,依赖会更复杂:torch、transformers、tokenizers、sentencepiece这些库对 Python 版本和 CUDA 版本都有要求。建议为这类项目单独创建环境,比如python=3.10,并查看对应框架的官方安装命令,不要凭感觉安装。PyTorch 的安装命令和 Python 版本、CUDA 版本强相关,直接pip install torch大概率会装到 CPU 版本,在本地跑大模型会慢很多。
9.5 内核命名也建议带上项目标识
注册内核时,--display-name不要只写Python 3,而是写成NLP Env甚至NLP Project (py39)。这样 Jupyter 界面里能一眼认出该选哪个内核,尤其是本机注册了多个项目内核之后。
9.6 定期清理不再使用的内核和环境
用以下命令可以查看本机注册的所有内核:
jupyter kernelspec list删除不需要的内核:
jupyter kernelspec remove old-kernel-nameconda 环境查看和删除:
conda env list conda env remove -n old-env环境长期不用会占用大量磁盘空间,一个 Anaconda 环境动辄几 GB,建议定期整理。
10. 总结与后续学习方向
到这里,你已经完成了一条完整的 NLP 本地开发链路:创建虚拟环境 → 安装 Jupyter 与 NLP 依赖 → 注册 Jupyter 内核 → 用 Notebook 运行关键词提取。这个过程看起来简单,但它解决的是很多 NLP 新手真正困扰的核心问题——环境混乱带来的挫败感。
下一步你可以从三个方向继续深入:
第一,把关键词提取换成真正的文本分类任务。用同样的环境尝试朴素贝叶斯或者逻辑回归对新闻文本分类,你会发现环境部分不需要变,只需要加数据和模型代码。
第二,尝试引入nltk做更标准的英文 NLP 预处理,比如去掉停用词、词形还原,再对比中文 NLP 的分词差异。理解中英文预处理的差异,是进入更深层 NLP 的必经之路。
第三,如果你打算做真正的大模型应用,比如基于预训练模型的文本摘要或情感分析,建议保留当前环境,在此基础上研究transformers库。届时你会依赖更大的依赖集,当前这套环境管理方法依然适用。
关于 Jupyter Notebook 和 Jupyter Lab 的选择,我的观点是:日常交互探索用 Lab,跑定时任务用 Python 脚本 + 虚拟环境,不要所有事情都挤在 Notebook 里完成。
把你本机环境从“一团乱麻”变成“一个项目一世界”,这本身就是 NLP 工程师走向工程化的重要一步。建议收藏这篇文章,等到你真的在 Jupyter 里踩到环境坑的时候,照着排查表逐条看,大概率能救急。