用Jupyter Notebook写东西这事,我前后折腾了好几年。最早接触它纯粹是为了给一个数据分析项目做交互式探索,那时候还在用Python自带的IDLE,每改一次代码就要重新跑一遍整个脚本,输出乱糟糟地堆在一起,想回头找某一段结果得翻半天。后来换到Jupyter Notebook,才意识到原来代码、输出、图表、说明文字是可以揉在同一个文档里按块组织的,整个思路瞬间就顺了。不过说实话,第一次装的时候也是各种不顺,依赖冲突、浏览器打不开、中文显示成方块、路径带中文直接报错,每一个坑我都踩过。这篇文章就把我从零开始装Jupyter Notebook、配置中文环境到正常使用的完整流程和踩坑记录写出来,希望帮你省掉那些没必要走的弯路。
这篇文章主要面向几类人:刚学Python、想在浏览器里交互式跑代码的新手;需要做数据分析、机器学习实验但每次跑完还要整理报告的工程师;以及单纯想把Notebook当实验记录本用的科研党。文章会覆盖安装步骤、中文环境配置、日常使用技巧,以及从热搜里看到的那些高频问题——比如单元格执行没反应、导入包报DLL加载失败、Notebook打不开等,每个问题我都会给出排查思路和实测有效的解决办法。
1. 安装前的核心准备
1.1 为什么建议用Anaconda而不是直接pip装
很多人第一次装Jupyter Notebook,第一反应是pip install jupyter一把梭。这个做法本身没错,但如果你在Windows上、并且之前已经装过其他Python包,很容易把依赖搞乱。我个人的建议是:如果目标是做数据分析、科学计算方向,直接装Anaconda是最省心的路径。原因有几点:
Anaconda自带Python解释器、Jupyter Notebook、NumPy、Pandas、Matplotlib这些常用库,装完就能跑,不需要一样一样去配。更关键的是它提供了一套独立的Python环境管理工具,你可以在里面创建不同的环境,每个环境有自己独立的包版本,互不干扰。比如你一个项目要用TensorFlow 2.x,另一个项目必须用PyTorch,普通pip装很容易互相踩依赖,conda环境就能轻轻松松把这两套东西隔离开。
如果坚持用原生Python加pip装的方案,也不是不行,但你需要自己处理很多细节。比如确保Python版本不低于3.8,检查pip和setuptools是否最新,装完之后还要确认Scripts目录在环境变量PATH里,否则命令行里敲jupyter会提示找不到命令。
1.2 Windows系统下的安装分步说明
无论选哪条路径,安装前都建议先创建一个专门的工作目录,并且目录路径不要包含中文和空格。这一步极其关键,因为Jupyter Notebook本身对中文路径的支持一直不够稳定。好,现在开始正式安装。
先看Anaconda方案。去官网下载Anaconda的最新版本安装包,双击运行,安装过程中有一个“Add Anaconda to my PATH environment variable”的选项,不同版本的显示不太一样,有些版本默认勾选,有些版本默认不勾选。我的建议是勾上,这样你后续在命令行直接敲jupyter、conda命令都能找到。安装完成后,打开命令行窗口,输入conda --version验证是否安装成功。确认conda可用后,创建一个新的虚拟环境并安装Jupyter:
conda create -n jupyter_env python=3.9 conda activate jupyter_env pip install jupyter notebook如果走纯pip路线,需要先确认Python已经装好,然后升级pip:
python -m pip install --upgrade pip pip install jupyter notebook这里有个细节:pip安装Jupyter会同时拉取一大堆依赖包,包括jupyter_core、nbformat、nbconvert、ipykernel等等。如果网络状况不太好,很容易在中途超时失败。解决方法是给pip换成国内镜像源,实测下来速度提升非常明显:
pip install jupyter notebook -i https://pypi.tuna.tsinghua.edu.cn/simple如果你用的是Anaconda,还可以用conda直接把Jupyter装进base环境:
conda install jupyter notebook装完之后,命令行输入jupyter notebook回车,正常情况下浏览器会自动弹出Notebook的首页,地址一般是http://localhost:8888/tree。
1.3 安装完成后验证环境是否正常
打开浏览器看到文件列表界面后,先别急着新建文件,花一分钟验证一下最基本的运行链路是否正常。点击右上角“New”按钮,选择Python 3创建第一个Notebook文件,在单元格里输入一行最简单的代码:
print("Hello Jupyter")然后按Shift + Enter执行。如果单元格左侧出现[1],并且下方打印出Hello Jupyter,说明核心链路是通的。这一步很重要,因为很多后续问题(比如执行没反应、内核连不上),如果能在这个阶段及时暴露出来,排查起来会容易得多。
2. 中文环境配置:字体、界面与路径问题
2.1 中文字体显示成方块的处理方案
Jupyter Notebook本身是支持中文显示的,但有些系统环境下中文字会全部显示成小方框或者乱码,尤其是Windows上中文字体渲染和Linux下的情况不太一样。这个问题的根源在于Notebook默认使用的字体族里没有包含合适的CJK(中日韩统一表意文字)字体。
比较好的处理方式是,在自定义CSS里把字体指定为系统自带的中文字体。Jupyter Notebook的配置目录在用户主目录下的.jupyter文件夹里,如果没有就自己创建,里面放一个custom子目录,然后在custom目录下新建一个custom.css文件:
/* custom.css */ body { font-family: "Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", sans-serif; } .CodeMirror pre { font-family: "Microsoft YaHei", "Consolas", "Courier New", monospace; }保存后刷新浏览器页面,中文显示问题基本就能解决。如果你用的是macOS,把Microsoft YaHei换成PingFang SC;Linux系统可以装fonts-noto-cjk包,然后在CSS里指定Noto Sans CJK SC。
2.2 代码单元格里的中文注释和字符串乱码问题
代码里的中文注释乱码,通常是因为文件编码问题。Jupyter Notebook的.ipynb文件本质上是JSON格式,默认使用UTF-8编码,一般不会出现编码问题。但如果你的环境变量里设置过PYTHONIOENCODING这类参数,或者某些第三方库在读取文件时强行用GBK解码,就可能触发编码异常。
最简单的排查方式是,在Notebook里执行以下代码,检查Python默认编码:
import sys print(sys.getdefaultencoding()) print(sys.getfilesystemencoding())正常情况下两个都应该是utf-8。如果filesystemencoding显示的是cp936或gbk之类的值,说明系统编码有问题。解决办法是在启动Jupyter Notebook前设置环境变量:
set PYTHONUTF8=1 jupyter notebook这个操作会让Python以UTF-8模式运行,从根上规避编码问题。
2.3 文件名和路径中的中文陷阱
很多人在Windows下创建了类似C:\用户\数据分析\测试.ipynb这样的路径,然后发现Notebook偶尔打不开文件、保存失败、或者内核启动时报错。这个问题的本质是Jupyter的某些底层组件在处理非ASCII路径时存在兼容性问题。
虽然在新版本中这个问题已经有所改善,但为了稳定起见,我的建议始终是:项目根目录用纯英文命名。比如在C:\Data\my_project\下建子目录,每个项目的目录名也尽量用英文字母和下划线。文档内部的内容用中文完全没有问题,受影响的主要是文件路径。
3. 日常使用:从单元格到标记文本
3.1 单元格的两种形态与快捷键
搞清楚Notebook的使用逻辑,其实核心就是理解“单元格”这个概念。一个Notebook文件由若干个单元格组成,每个单元格可以包含代码,也可以包含格式化的文本内容。代码单元格按Shift + Enter执行,输出会直接显示在单元格下方;文本单元格按Shift + Enter后会渲染成格式化的正文。
日常操作里最常用的几个快捷键:
| 快捷键 | 作用 |
|---|---|
| Shift + Enter | 执行当前单元格并切换到下一个 |
| Alt + Enter | 执行当前单元格并在下方插入新单元格 |
| Esc + A / Esc + B | 在上方/下方插入单元格 |
| Esc + M | 把当前单元格切换为Markdown文本状态 |
| Esc + Y | 把当前单元格切换为代码状态 |
| Esc + D + D | 删除当前单元格 |
| Esc + Z | 撤销删除单元格 |
这些快捷键在命令行模式下生效,所谓命令行模式是指当前选中的单元格边缘是蓝色高亮,而不是处于编辑状态时的绿色边框。
3.2 Markdown目录语法与排版技巧
Jupyter Notebook里的Markdown单元格支持标准的Markdown语法,包括标题、列表、链接、图片、表格等。用#到######可以定义一到六级标题,其中一级标题通常用作文档总标题,二级标题作为章节起点。
有个高频需求是在长文档里自动生成目录。Jupyter Notebook官方的界面里并没有内置目录面板,但有两个思路可以解决。第一个思路是安装jupyter_contrib_nbextensions扩展包,里面自带一个Table of Contents插件,装好之后Notebook顶部会出现一个目录按钮,可以一键跳转到任意标题。安装命令:
pip install jupyter_contrib_nbextensions jupyter contrib nbextension install --user装完后启动Notebook,在“Edit > nbextensions config”里勾选Table of Contents (2),刷新页面后标题旁边会多出目录符号。
第二个思路是在Markdown单元格里手动写锚点跳转。Jupyter会为每个标题自动生成锚点ID,比如## 3. 日常使用对应的锚点是#3.-日常使用,用如下语法就可以从任意位置跳转过去:
[跳转到日常使用章节](#3.-日常使用)这个方法的优点是不需要额外装插件,缺点是需要自己维护锚点名称,标题一旦改动,链接就失效了。
3.3 代码自动补齐和补全扩展的配置
默认状态下,Jupyter Notebook是有基础自动补齐功能的,在代码单元格里输入部分内容后按Tab键,会弹出补齐建议。但如果你想要更智能的补全体验——比如按函数名联想参数、按变量名联想类型——就需要借助第三方扩展。
目前最常见的选择是jupyterlab-lsp配合python-lsp-server,不过这个方案主要是JupyterLab的。对于经典Notebook界面,则可以用nbextensions里的Hinterland插件,它能让自动补齐在打字过程中随时弹出,不需要主动按Tab。安装方式:
pip install jupyter_contrib_nbextensions jupyter contrib nbextension install --user jupyter nbextension enable hinterland/hinterland启用后重新加载页面,在代码单元格里输入num,就会看到numpy的拼写建议实时弹出。实测下来,在长变量名多、库名多的项目里,这个功能能明显减少拼写错误和反复切换文档查看API的时间。
4. 常见问题与排查技巧实录
4.1 单元格执行代码没有任何反应
这个问题在热搜词里出现频率极高,也是最容易吓到新手的问题之一。现象是:你在单元格里输入代码,按Shift + Enter,但左侧没有出现[1],页面也没有任何输出,甚至连光标都不动了。
根据我自己的排查经验,这个问题通常和内核(Kernel)的连接状态有关。Jupyter Notebook的执行流程是:浏览器把代码发送给Notebook服务器,服务器再把代码交给独立的Python内核进程执行,最后把结果推回浏览器。其中任何一环断了,都会导致“执行没反应”的现象。
第一步,先看工具栏右上角有没有“Kernel”字样,旁边如果显示一个空心圆圈,说明内核已经断开。点击菜单栏的Kernel > Restart重启内核,很多情况下都能恢复。第二个可能是内核进程还在,但消息队列卡住了。这种时候直接在菜单里选择Kernel > Restart & Clear Output,把输出全部清掉再试。
如果重启后依然没有反应,就需要关注内核是否真的启动成功。在命令行运行Notebook的那个终端窗口里,看看有没有报错堆栈。我遇到过几次是因为ipykernel和Jupyter版本不匹配,升级一下就好:
pip install --upgrade ipykernel jupyter_client4.2 运行Jupyter时出现DLL加载失败
热搜词里那条“importerror: dll load failed while importing rpds”也是我身边同事经常踩的坑。这个报错看起来是在导入某个包时Windows动态链接库加载失败,根源通常和包的二进制版本不兼容有关。
rpds是一个底层Rust实现的库,很多像jsonschema这类上层包会依赖它。如果这里报加载失败,大概率是你当前Python环境里rpds的版本和系统架构不匹配。最简单的处理办法是强制重装:
pip uninstall rpds -y pip install rpds -i https://pypi.tuna.tsinghua.edu.cn/simple如果重装之后还报同样的错误,可以考虑升级pip后再装:
python -m pip install --upgrade pip还有一种隐蔽的原因是你本机上存在多个Python安装,导致pip装到了A环境、运行用的却是B环境。排查方法是在Notebook里执行:
import sys print(sys.executable)看到当前内核用的Python解释器路径,再在命令行那边用同一个解释器的pip重新安装rpds,问题就能对齐了。
4.3 Jupyter Notebook打不开或启动后自动关闭
打不开的情况一般有两类表现:一是命令行输入jupyter notebook后,浏览器没有自动弹出页面;二是浏览器打开了地址,但页面一直转圈或者显示“无法访问此网站”。
先说第一种。浏览器没有自动弹出来,但你在终端里看到有http://localhost:8888/tree这样的输出,那就手动把地址复制到浏览器里打开。如果终端里也没有输出地址,说明启动过程中就出错了。常见原因之一是端口被占用,Jupyter默认用8888端口,如果之前启动过实例没关干净,新的进程就会起不来。解决办法是换端口:
jupyter notebook --port 8889还有一种可能是防火墙拦截了本地端口。Jupyter启动时会监听本机地址,正常情况下不会有防火墙弹窗,但某些安全软件会默认拦截所有非白名单端口的本地监听,这种情况下需要在防火墙设置里放行。
如果是第二种情况,也就是页面打不开或者一直转圈,大概率是浏览器的原因。Jupyter很多早期版本对某种特定浏览器的兼容性有坑,最典型的是某些旧版本Chrome和Edge对WebSocket连接支持有问题。可以试一下用Firefox打开http://localhost:8888/tree,或者清理浏览器缓存、切换无痕模式再试。
4.4 按热搜词继续深挖:nvm集成和网页版方案
热搜词里还有两条值得聊一下:jupyter notebook nvim和jupyter notebook网页版。
先打包回复前面那个。如果你平时主力编辑器是Neovim,又不想离开编辑器去浏览器里操作Notebook,可以使用jupytext工具把.ipynb转换成.py文件,在Neovim里编写基于文本标记的Python文件,再通过命令同步成.ipynb格式。这种方式适合习惯纯文本编辑、喜欢用Git做版本管理的人。Neovim里也可以配合molten-nvim插件,它能在Neovim的浮动窗口里直接执行Notebook单元格,类似Jupyter的交互体验。
再说网页版。很多人一直误以为Jupyter Notebook必须装在本机才能用,其实它可以部署在远程服务器上,通过浏览器访问。简单做法是在服务器上启动:
jupyter notebook --no-browser --ip=0.0.0.0 --port=8888但要注意,直接暴露公网是很危险的操作,任何知道地址的人都能访问。稳妥做法是用密码保护:
jupyter notebook password执行后会提示输入密码,然后启动Notebook时就会要求验证。远程部署的场景适合给团队共享分析环境,或者让计算资源跑在性能更好的机器上,而本机只负责浏览器交互。
5. 实际项目:从安装到跑通一个真实分析流程
5.1 一次完整的数据探索项目演练
光说不练假把式,我拿一个最简单的示例项目来演示完整流程。假设我们要分析某电商网站的销售数据,文件是sales.csv,包含日期、商品类目、销售额、订单量几个字段。
第一步,在工作目录里启动Jupyter Notebook,新建一个Notebook,命名为sales_analysis.ipynb。在第一个Markdown单元格里写项目背景和数据结构说明,然后用代码单元格读取数据:
import pandas as pd df = pd.read_csv("sales.csv", encoding="utf-8") print(df.shape) print(df.dtypes)看到shape输出后,如果数据量很大比如几万行,运行时会稍微慢一些,但按Shift + Enter后左下角的In [1]变In [1]并出现输出,说明一切正常。
第二步做数据清洗,处理缺失值和重复记录:
df.isnull().sum() df = df.drop_duplicates().dropna(subset=["销售额"])这里有个细节,当你执行过第一次代码后,df这个变量就存在于内核的全局命名空间里,后续单元格可以继续使用它。如果中途改了代码想重跑,不需要重启内核,直接选中相关单元格从上到下依次执行即可。但如果你改动的是前序单元格的变量名,那后续引用旧变量名的单元格就会因为变量不存在而报NameError,这种时候要么把后面的代码同步改掉,要么干脆用Kernel > Restart & Run All全部重跑一遍。
第三步,画一个销售额的趋势图:
import matplotlib.pyplot as plt df["日期"] = pd.to_datetime(df["日期"]) daily_sales = df.groupby("日期")["销售额"].sum() daily_sales.plot(kind="line") plt.show()这个图会直接渲染在代码单元格下方,并且支持鼠标交互放缩查看细节。
5.2 导出报告与分享协作
分析完成后,你多半想把结果分享给同事或者存成文档归档。Jupyter的导出功能可以直接把Notebook转成HTML、Markdown、PDF等格式。最常用的是File > Download As > HTML,导出的HTML文件保留所有代码、输出和图表,直接用浏览器打开就能看,不需要装任何软件。
如果你需要生成PDF,推荐先导出为HTML,再用浏览器的“打印”功能保存成PDF。直接导出PDF的话,Windows下经常遇到中文显示异常、中文字体缺失的问题,另外还需要额外安装TeX环境,麻烦且容易失败。用HTML转PDF的方式就不用碰这些。
如果团队用Git做版本管理,Notebook的.ipynb文件在合并代码时经常会冲突,因为里面保存了输出结果、执行计数等信息,稍微一改就是一大串JSON变化。我的经验是,在.gitignore里排除掉Notebook文件,或者用jupytext等工具把Notebook另存一份.py脚本来做版本管理,分析结果靠导出的PDF或HTML来分享,代码靠.py文件来review,两边互不干扰。
5.3 关于JupyterLab和Notebook的选择
写到这里顺便再说一句,Jupyter生态里除了经典Notebook,还有一个升级版的JupyterLab。JupyterLab可以理解为Notebook的集成开发环境版本,支持多标签页、拖拽布局、文件管理器侧边栏,还能直接打开终端、编辑器等工具。如果你的使用习惯是专注在单个Notebook文件上,经典界面足够;如果你需要同时处理多个Notebook、写Python脚本、看数据文件、在终端里装包,JupyterLab要顺手得多。
启动方式也很简单:
jupyter lab很多新版本Anaconda默认就带JupyterLab。对我个人来说,日常简单分析用经典Notebook多点,因为界面更简洁、加载更快;但做稍微复杂一点的项目我会切到JupyterLab,一边开着Notebook,一边开着终端,省掉来回头脑切换上下文的时间。
6. 几点经验教训写在最后
装Jupyter Notebook这个事本身不算复杂,但因为涉及的组件比较多,一旦出问题就容易让人一头雾水。根据我这几年的使用经验,几个容易踩坑的点再啰嗦一遍:
虚拟环境一定要从一开始就养成习惯。很多人图省事,什么都装在base环境里,时间一长各种包版本互相打架,最后只能含泪重装Python。用conda创建独立的虚拟环境,每个项目一套依赖,刚开始多花两分钟,后面能省一整天。
中文问题的核心在编码和字体两件事。文件路径用英文,代码里随便用中文,字体显示问题用custom.css解决,编码问题用PYTHONUTF8=1兜底,基本上就齐活了。
执行没反应、内核崩溃这类问题,记住一条排查主线:先看内核状态,再重启内核,最后对齐Python解释器路径和包版本。90%的情况都能在这三步里解决。
最后一个个人体会:Jupyter Notebook最大的价值其实不是跑代码,而是把“思考过程”和“执行结果”粘在一起。写代码的时候顺便把为什么要这么写、结果说明了什么,都用Markdown记在旁边,一份Notebook就是一份会执行的分析报告。坚持用这个习惯一段时间,你会发现自己对数据的理解深度提升得很快。