用 Jupyter 的人,十个里有七八个都经历过这种尴尬:明明用 conda 老老实实建了好几个环境,打开 Jupyter Notebook 一看,翻来覆去还是 base 里那个老内核。换个环境写的代码,一到 Notebook 里就 import 报错,环境切换变成了一场体力活。更糟的是,好不容易跑通了,某天又冒出来一个 jupyter permissionerror:[errno 13] permission denied,整个人直接懵住。
这篇文章就是把这些事彻底捋清楚:如何配置 Anaconda 多环境,把每个 conda 环境注册成 Jupyter 的独立内核,然后在 Notebook 里像换台一样切换环境。我会从 Anaconda 安装开始讲,一步步到环境创建、内核注册、权限报错排查,最后补上默认保存路径和团队协作同步这些进阶操作。不管你是刚接触 Python 的新手,还是已经被环境问题折磨过几轮的老手,按这套流程走一遍,就能在 Jupyter 里自由切换所有环境,不用再为跑一段代码反复折腾。
1. 项目概述:为什么 Jupyter 需要多环境切换
1.1 环境混乱,几乎是所有 Python 用户的必修课
我见过太多人,把 Anaconda 装完之后所有包都往 base 里塞。今天 conda install 一个,明天 pip install 一个,也不管依赖冲突,最后 base 里装了几百个包,每次 conda update 都心惊胆战,生怕哪个库被升级搞挂。这种问题在 Jupyter 里会被放大,因为你一旦在 base 里把环境搞坏了,整个 Notebook 里的代码全部遭殃,项目直接瘫掉。
真实的项目需求往往是分散的。日常数据分析需要 Python 3.10 配 pandas 和 matplotlib;机器学习项目需要 Python 3.9 配 scikit-learn 和 TensorFlow 2.x;深度学习研究可能需要 Python 3.8 配 PyTorch 1.13;偶尔还要写点接口、做自动化,又要 Python 3.11。这几个技术栈放在同一个环境里,光依赖冲突就够喝一壶了。可如果建了多个 conda 环境,却没有把它们注册成 Jupyter 内核,那喜欢用 Notebook 写代码的数据分析师和研究型开发者,就完全享受不到环境隔离的好处。
所以多环境加多内核,不是锦上添花,而是 Python 工程实践里的基本盘。把环境和内核的关系理顺,等于给自己的工作流装了一个可靠的调度系统。
1.2 Jupyter 内核与 conda 环境到底什么关系
先纠正一个经常被混淆的概念:conda 环境和 Jupyter 内核不是一回事。conda 环境是一套完整的 Python 运行环境,包含独立的 Python 解释器、pip、以及各种第三方库,环境之间完全隔离。Jupyter kernel 则是 Jupyter 前端用来执行代码的“后端进程”,你每打开一个 Notebook,背后其实就连到了一个 kernel,这个 kernel 决定代码最终由哪个 Python 解释器、哪组依赖包来执行。
我习惯用一个生活化的类比。每个 conda 环境就像一间独立的工作室,里面有专属工具箱,Python 版本、库版本各不一样。Jupyter 是前台接待处,你在浏览器里写的代码,最终要交给后台某间工作室去执行。默认情况下,前台只知道 base 这一间工作室,其他工作室虽然已经建好了,但没有“登记”到前台,所以你在 Jupyter 的新建菜单里看不到它们,也切不过去。
注册内核,本质就是给每个环境做一次“前台登记”。登记之后,Jupyter 就知道该调用哪个环境里的 Python 解释器了。很多人问我“为什么 conda 环境里明明有这个包,Jupyter 里却 import 不到”,答案基本都指向这里:当前 Notebook 连着的 kernel 根本不是那个 conda 环境,或者那个环境压根就没注册成内核。理解了这层关系,后面对付内核切换和权限报错就有底气了。
2. 环境准备:Anaconda 与 Jupyter 的安装配置
2.1 Anaconda 安装避坑指南
如果你还没装 Anaconda,先想清楚两件事。第一,装全量版 Anaconda 还是 Miniconda?全量版开箱即用,自带一百多个常用科学计算包,适合不想折腾的用户;Miniconda 只有 conda 和 Python,其他包按需安装,适合喜欢掌控环境的人。我个人偏向 Miniconda,因为 base 环境天然干净,和多环境多内核的思路特别搭,需要什么装什么,不产生一堆用不到的包。
第二,安装路径千万别乱选。Windows 下不要装在系统目录下,比如 C:\Program Files 这种地方,更不要装在带中文、带空格的路径里。我遇到过用户把 Anaconda 装到“E:\软件\Anaconda3”,结果 conda 命令和环境激活各种报错,最后只能卸载重装。路径里的中文和空格,是很多诡异问题的根源之一,其中就包括注册内核时权限不足、找不到执行路径这一类的报错。
安装完成之后,Windows 用户强烈建议用 Anaconda Prompt 或者 Miniconda Prompt 操作,因为普通 cmd 有可能没把 conda 写进 PATH。如果在 cmd 里输入 conda 提示“不是内部或外部命令”,不用急着重装,先检查系统环境变量,把 Anaconda3 的 Scripts 目录加进 PATH 就行。macOS 和 Linux 用户在安装结束后记得执行 source ~/.bashrc 或 source ~/.zshrc,让 conda 初始化生效。装完验证一下版本,conda --version,能正常输出就没问题。
2.2 安装并启动 Jupyter Notebook
新版 Anaconda 和 Miniconda 的基础环境都不一定自带 Jupyter,尤其是 Miniconda,基本需要手动装。命令不复杂:
conda install -c conda-forge jupyter notebook这里我同时装了 jupyter 和 notebook 两个包。jupyter 是主程序,notebook 是经典的笔记本界面。如果你喜欢 JupyterLab,就再加一个 jupyterlab,它在多标签、文件管理的体验上已经比传统 notebook 好很多了。我平时的习惯是 notebook 和 lab 都装上,根据场景选。
启动的方式是在激活对应环境后执行:
jupyter notebook或者:
jupyter lab启动后终端会打印一段日志,一般会自动打开浏览器。如果浏览器没自动弹出来,就把日志里 http://localhost:8888 那串地址复制到浏览器手动访问。这里有个人人都遇到过的细节:在某个目录打开终端,执行 jupyter notebook,浏览器里看到的文件列表就是那个目录的内容。因为 Jupyter 默认把启动时的当前目录当成根目录,新建 Notebook、浏览文件都从这里展开。这个行为后面我会讲怎么改,先把环境搭起来。
3. 核心操作:创建多环境并注册为 Jupyter 内核
3.1 用 conda 创建多个 Python 环境
假设现在要建三个环境:一个叫 py310,用于日常数据分析,Python 用 3.10;一个叫 torch 项目,用于深度学习,Python 用 3.8;一个叫 tf 项目,Python 用 3.9。三条命令跑一遍:
conda create -n py310 python=3.10 -y conda create -n torch python=3.8 -y conda create -n tf python=3.9 -y这里的 -n 是 name 的缩写,后面跟环境名;python=3.10 指定初始 Python 版本;-y 表示遇到确认提示直接同意。很多新手在环境命名上不讲究,取的什么“深度学习环境”“数据分析”这种带中文带空格的名字,后面在命令行里要加引号不说,在 Jupyter 内核注册时还容易出些莫名其妙的问题。我建议统一用英文小写加下划线,一眼能看出用途,比如 py310、torch113、tf24。
创建好之后,有几个命令会经常用:
conda env list # 查看所有环境 conda activate py310 # 激活某个环境 conda env remove -n 旧环境名 # 删除无用环境 conda create -n 新环境 --clone 旧环境 # 克隆现有环境每个环境创建后,按需安装自己项目的包。比如激活 py310 之后执行:
conda activate py310 pip install pandas matplotlib numpy这里想多说一句:基础环境创建好之后,先别急着装一堆包。确认环境能激活、pip 能正常工作,再逐渐加依赖,这样后面注册内核和排查问题时,干扰因素会少很多。
3.2 每个环境安装 ipykernel 并注册内核
这是整篇文章的核心环节,也是最干的部分。要让一个 conda 环境出现在 Jupyter 里,必须在环境内部安装 ipykernel,然后执行一次注册命令。拿 py310 举例:
conda activate py310 conda install ipykernel -y python -m ipykernel install --user --name py310 --display-name "Python 3.10 (py310)"重点解释一下这条注册命令的三个参数,很多人不懂含义就乱抄,出问题也不知道怎么改。
--user 表示把内核注册到当前用户目录,而不是系统级目录。这一步极其关键,不加 --user 时,ipykernel 会尝试写入系统级目录,在 Windows 上经常因为权限不足直接报 PermissionError,Linux 和 macOS 上则可能要求 sudo。个人电脑上我强烈建议一律加 --user,安全又省事。
--name 是内核的唯一标识,内部用的小写标识符,最好只用字母、数字、下划线。这个 name 会作为内核配置目录的文件夹名,所以别用空格和特殊符号。
--display-name 是显示在 Jupyter 界面菜单里的名字,可以随意,包含空格和中文都没问题,完全按你的习惯来。
三个环境都注册一遍之后,用命令检查注册结果:
jupyter kernelspec list输出里会列出所有可用内核,base 环境通常显示为 python3,我们自己注册的 py310、torch、tf 都会列在这里。到这一步,再打开 Jupyter Notebook,新建文件时就能在选项里看到“Python 3.10 (py310)”这样的名字了。
还有一个必须强调的操作细节:注册内核命令,一定要在目标环境的激活状态下执行。只装了个 ipykernel 不激活环境就注册,注册出来的内核指向的还是 base 的 Python,等于白干。想确认当前到底在哪个解释器环境,可以执行:
import sys print(sys.executable)打印出来的路径如果是目标环境的 Python,那说明环境激活正确,接下来注册才能生效。
如果环境属于内网机器,无法直接 conda install ipykernel,也可以先激活环境,再用 pip 安装:
conda activate 环境名 pip install ipykernel然后再执行注册命令。逻辑完全一样。
3.3 内核命名、改名与 kernelspec 管理
内核注册之后,系统会在特定目录生成一组配置文件,这个目录体系统称 kernelspec。Windows 下路径一般在 C:\Users\你的用户名\AppData\Roaming\jupyter\kernels\,Linux 和 macOS 下一般在 ~/.local/share/jupyter/kernels/。每个内核是一个子目录,里面有一个 kernel.json,记录了启动这个内核要执行的命令、运行环境等关键信息。
如果某天想改内核的显示名,比如想把“Python 3.10 (py310)”改成“数据分析用Python3.10”,不用大动干戈,直接编辑 kernel.json 里的 display_name 字段,或者重新跑一遍 ipykernel install 命令,用新的 --display-name 覆盖即可。
但如果想改内核的内部 name,也就是那个目录名,我更推荐先删除再重新注册的流程,避免手改路径导致启动报错:
jupyter kernelspec remove py310删掉之后再按 3.2 节注册一次,换一个新的 --name。为什么不直接改目录名?因为 kernel.json 里通常记录了环境路径,改目录名时漏改任何一处,都可能让内核启动失败,到时候排查起来反而更费时间。
我自己维护内核清单的习惯是:每季度清理一次,用 jupyter kernelspec list 看一眼,把已经废弃的项目环境对应的内核删掉。内核注册得越多,启动 Jupyter 时扫描的负担也越重,保持精简对整个环境的响应速度有好处。
4. 实战问题:内核切换与 PermissionError 排查实录
4.1 Notebook 中切换内核的正确姿势
环境注册好了,切换内核的入口主要有三个。新建 Notebook 时,传统 notebook 界面通过 New 下拉菜单选内核,JupyterLab 则是在启动界面点对应的图标。已经打开的 Notebook,通过菜单里的 Kernel -> Change Kernel 切换。切换之后,当前 Notebook 的所有单元格在后续执行时都会使用新内核。
这里有个容易踩的坑:切换内核并不会自动重启 Notebook 的变量状态。如果你在旧内核里已经定义了一堆变量,切换内核之后再执行单元格,新内核可没有这些变量,必须重新运行前面的代码。所以我的习惯是:切换内核之前,先把重要结果保存一下;切换后直接 Kernel -> Restart & Run All,让代码从干净的全局环境重新跑一遍,避免出现变量残留导致的诡异结果。
再分享一个能帮你快速定位“当前 Notebook 到底连的是哪个环境”的命令,遇到 import 报错时特别好用:
import sys print(sys.executable)打印出来的路径会明确指出当前 Python 解释器在哪。如果发现路径不是目标环境的,那就说明内核还连着别的环境,切一下内核或者重新注册,问题基本就能定位。
还有一点想提醒:内核切换不影响 Notebook 文件的保存位置,文档存在哪就一直存在哪。但不同内核的 Python 版本可能不一样,同一个 Notebook 里的代码可能在 Python 3.8 能跑,切到 3.10 就报了 API 变化相关的错误。所以我的建议是,按项目固定使用某个内核,别在同一个 Notebook 里频繁切换不同 Python 大版本的环境,省得被版本差异折腾。
4.2 PermissionError [Errno 13] 的常见成因与解法
来聊聊热词里出现频率很高的 jupyter permissionerror:[errno 13] permission denied。我排查过的权限报错,基本可以归成三类,每一类的成因和解法不太一样。
第一类是注册内核时遇到的权限报错。报错信息通常长这样:
Could not install kernelspec ... PermissionError: [Errno 13] Permission denied: '/usr/local/share/jupyter/kernels'原因非常明确:注册时没加 --user,ipykernel 默认尝试往系统级目录写,但当前用户没权限。解决办法就是重新注册,记得加上 --user:
python -m ipykernel install --user --name 环境名 --display-name "显示名"如果确实需要系统级内核,那再考虑 sudo(Linux、macOS)或者管理员终端(Windows),但个人电脑完全没必要,加 --user 就够了。
第二类是打开 Notebook、运行代码时出现的 permission denied。这种情况通常是指向目录权限问题。最常见的是把 Notebook 文件放在当前用户没有写权限的目录里,比如 C:\Users\Public、/root 目录,或者共享盘的只读目录。Jupyter 在自动保存时会在同名目录下创建 .ipynb_checkpoints 子目录,写不进去就会报权限错误。解决思路是换一个当前用户有完整读写权限的工作目录,或者用 5.1 节的方法设置默认保存路径,把工作区固定到可写的地方。
第三类是 Windows 上比较隐蔽的情况:曾经用管理员身份运行过一次 Jupyter,导致某些文件或目录的属主变成了管理员组,之后再以普通身份打开 Jupyter,就发现读取不到、保存失败。这种问题的排查思路是先看清楚报错指向的文件路径,右键看属性里的安全权限,把当前用户加入完全控制;如果那个文件本身不重要,直接删掉让 Jupyter 重新生成,反而更利索。
排查权限问题的通用步骤我也总结一下。先看完整报错,找到具体是哪个文件、哪个目录没有权限;再判断是内核注册目录、Notebook 文件目录还是检查点目录;然后针对不同目录处理权限,或者就像前面说的,直接加 --user、换工作目录,别在一个权限问题上钻牛角尖。
4.3 高频问题速查表
整理一个排查表,覆盖我最常被问到的几类情况:
| 问题现象 | 常见原因 | 推荐解法 |
|---|---|---|
| Jupyter 里看不到新建的环境 | 环境内没装 ipykernel,或没执行注册命令 | 激活该环境后执行 python -m ipykernel install --user --name 环境名 --display-name "显示名" |
| 运行单元格时 ModuleNotFoundError | 当前内核不是包所在的环境 | Kernel -> Change Kernel 切换,或用 sys.executable 确认解释器路径 |
| 注册内核时报 PermissionError | 注册命令没加 --user | 重新执行并加上 --user |
| 打开或保存 Notebook 时 permission denied | Notebook 所在目录无写权限 | 换可写目录,或用 --notebook-dir 指定工作目录 |
| 内核启动失败,报找不到解释器 | kernel.json 路径被改坏 | 用 jupyter kernelspec remove 删除,再重新注册 |
| conda 环境装完新包后 Jupyter 里 import 不到 | 内核进程还保留着旧的包加载状态 | Kernel -> Restart,必要时 Restart & Run All |
| 注册的内核指向错误的 Python 环境 | 注册时没激活目标环境 | 激活目标环境后重新注册,并用 sys.executable 验证 |
这张表覆盖不了所有奇怪情况,但面对报错时,先看错误信息指向什么文件、什么目录,再对着表查,通常几分钟就能定位到问题。
5. 进阶配置:默认保存路径、内核维护与团队协作
5.1 修改 Jupyter 默认保存路径
很多人问过 jupyter notebook 默认保存路径怎么改。默认情况下,Jupyter 的文件根目录就是你启动命令时所在的那个目录,这导致不同终端启动会得到不同的目录,文件散落各处。更稳的做法是写配置文件,固定工作目录。
先生成配置:
jupyter notebook --generate-config生成的文件一般在 ~/.jupyter/jupyter_notebook_config.py。用文本编辑器打开,找到这一行:
# c.NotebookApp.notebook_dir = ''把注释去掉,填上你想要的路径,比如:
c.NotebookApp.notebook_dir = 'D:/notebooks'改完保存,重启 Jupyter 生效。这个配置是用户级别的,针对当前操作系统的用户名下的所有 Jupyter 实例。我在写教程、做分享之前都会改这个,因为总不能让人看到 home 目录下一堆乱七八糟的文件。
除了写配置,启动时也可以临时指定目录:
jupyter notebook --notebook-dir=D:/notebooks写配置的好处是固定工作区,不用每次记命令行参数。如果是团队共用一台服务器的场景,建议每个人用不同的端口启动 Jupyter,配合不同的 notebook_dir,避免互相看到对方的文件,也避免配置互相干扰。
5.2 内核清理与 conda 环境瘦身
随着项目越做越多,环境会膨胀到让你意外的程度。我见过一年下来十几二十个 conda 环境、Jupyter 内核列表翻好几页的机器,启动 Jupyter 都慢吞吞的。定期清理是正经事。
内核清理命令:
jupyter kernelspec list # 查看现有内核 jupyter kernelspec remove 内核名 # 删除不用的内核conda 环境清理方面,常用的几条:
conda clean --all # 清理 conda 缓存和下载的安装包 conda env list # 检查是否有废弃环境 conda env remove -n 旧环境名 # 删除废弃环境另外建议 pip 安装依赖时多用 requirements.txt,或者用 pip freeze 导出清单。这样删掉环境、重建环境时不用回忆装过哪些包,成本会低很多。别指望 conda env remove 之后再手动装二十个包还能记住版本,写成文件一劳永逸。
再分享一个个人习惯:base 环境永远是“最小化”状态,只放 conda、pip、ipykernel 这类基础设施,不往里装项目依赖。这样做的好处是,不管哪个项目环境出了问题,base 还能在“干净的基地”里做修复操作,比如重装 pip、启动 conda、注册新的内核。
5.3 团队协作中用 environment.yml 同步环境
如果是小组一起做项目,每个成员都手动 conda create 环境、手动 pip install,最后大家的环境版本大概率会分叉。更稳的做法是导出一份 environment.yml,全体成员基于这份文件创建一致的环境。
导出当前环境的依赖清单:
conda activate 项目环境 conda env export > environment.yml拿到文件的人执行:
conda env create -f environment.yml环境名写在 yml 文件里,所以大家创建出来的环境名都是同一个,注册内核时再用同一套命名规范,团队内部就不会出现“都在跑同一个项目,环境名却五花八门”的情况。
这份 yml 文件建议放项目根目录,纳入版本控制。更新依赖的流程是:有人新增了包,确认跑通后重新导出一份 yml 提交。其他人拉取代码后执行 conda env update -f environment.yml 就能同步。
最后提醒一个坑:conda env export 导出的文件里会带上每个包的 build 哈希,换机器或者跨平台时,有可能因为哈希值不匹配导致创建失败。遇到这种情况,可以改用 conda env export --from-history,导出的只是你手动指定过的包,不带哈希,跨平台兼容性更好,团队协作时往往比一堆哈希报错省心得多。
我在实际使用中还有一个体会:多环境多内核这套方案,最怕的不是环境多,而是命名乱。曾经有个同事把环境名取成 a、b、c,半年之后没人知道哪个环境对应哪个项目,最后全部推倒重来。从第一天开始就用“项目名+Python版本”这样的规则来命名环境和内核,看起来是个小习惯,长期下来能省掉大量沟通和排查成本。希望这篇从安装、注册、排查到进阶配置的完整流程,能帮你把 Jupyter 和 conda 的关系理顺,下次再遇到“Notebook 里找不到环境”或者权限报错,至少不用再对着屏幕发愁了。