Jupyter 这个东西,做数据分析和机器学习的朋友应该都不陌生。我一七年刚开始用 Notebook 的时候,其实挺嫌弃它的,觉得就是个带输出的编辑器,写大工程还是得靠 PyCharm。结果用到现在,它反倒成了我日常干活的默认工具。不是因为它多强大,而是因为交互式开发、数据探索、写实验记录、甚至临时给同事演示一个逻辑,都是它最顺手。
这篇整理的内容不是官方文档的翻译,而是我这些年实际用下来的经验。从安装配置、目录总览、常用快捷键,到内核管理、报错排查、最后把 Notebook 变成自媒体产出工具,每一步都有真实场景和踩坑记录。不管你是刚装好 Jupyter 的新手,还是用了一段时间但老觉得不够顺手的进阶用户,这篇应该都能让你找到几个值得收藏的点。
1. 环境就绪:安装与配置的第一关
1.1 Anaconda 还是 pip:两条路线怎么选
先说安装。新手朋友最常问的问题是:我该用 Anaconda 还是直接 pip install?我的建议很直接——做数据科学,优先 Anaconda;只做轻量 Python 开发,那就 pip 省事。
Anaconda 的好处是它自带了一套完整的数据科学生态,Python 解释器、NumPy、Pandas、Matplotlib、Scikit-learn 这些都预装好了,Notebook 和 Lab 也是开箱即用。对于不想折腾环境依赖的人,这能省掉很多时间。而且 Conda 管理虚拟环境比 pip + virtualenv 直观不少,后续切换 Python 版本、装 GPU 版 PyTorch 这种事,conda 都顺手。
bash复制# 安装 Anaconda 之后,确认 notebook 可用
conda install jupyter notebook
jupyter --version
如果你的电脑配置一般,或者只是想跑个简单的脚本,那用 pip 就够了:
bash复制pip install notebook
pip install jupyterlab
这里有个细节值得注意:Jupyter 和 Jupyter Notebook 是两个包,前者是元包,会自动拉取核心组件;后者是具体的经典版 Notebook 界面。如果你只装了 jupyter,启动时可能找不到 notebook 命令,所以安装完最好用 jupyter --version 确认一下。
另外一个稍微老派但依然有用的场景:Windows 7 上装 Jupyter。虽然 Py 3.9 之后的版本不再支持 Win7,但如果你公司电脑还锁在 Win7,可以用 Python 3.8 的安装包配合 pip 装。实测下来,Notebook 6.x 在 Win7 下跑得还算稳,Lab 会吃力一点,建议按需选择。
1.2 配置文件到底在哪:密码与远程访问设置
每次在新机器上配 Jupyter,我都要先奔着配置文件去。默认情况下,这个文件不是自动生成的,你需要先手动创建一次:
bash复制jupyter notebook --generate-config
生成位置一般在这里:
- Windows:C:\Users\你的用户名.jupyter\jupyter_notebook_config.py
- macOS / Linux:~/.jupyter/jupyter_notebook_config.py
这个文件里有几百个配置项,但对于大多数人来说,最常改的只有两个:监听地址和访问密码。
先说密码。我见过不少朋友直接在上面设成 c.NotebookApp.password = '123456',结果下次重启发现登录报错。原因是 Notebook 不能直接用明文密码,它要的是经过哈希处理的字符串。想生成这个哈希,有标准做法:
bash复制# 在 Python 里生成密码哈希
from notebook.auth import passwd
passwd()
回车之后会让你输入两次密码,然后把输出的一长串 argon2: 开头的字符串,复制到配置文件里:
python复制c.ServerApp.password = 'argon2:xxxxxxxxxxxx'
c.ServerApp.allow_remote_access = True
注意:不同版本 Jupyter 配置项可能不一样。新版本用 c.ServerApp.password,老版本用 c.NotebookApp.password。如果你配置后没生效,优先检查这个前缀是不是对上了。
那密码怎么关闭?两种方式:一种是把配置文件里的 password 项注释掉,然后重启服务;另一种是直接用命令:
bash复制jupyter notebook password # 按提示输入新密码
# 如果想清除密码,直接删掉配置文件中的 password 行,或者执行:
jupyter notebook --ServerApp.password=''
热词里有个“jupyter lab 密码关闭配置”,其实就是同一个文件、同一个字段,Lab 和 Notebook 共用这套配置。只是 Lab 启动的时候会读同一份配置文件,所以改完重启即可。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 界面与目录:把工作区盘成自己想要的样子
2.1 侧边显示标题总览:目录插件的安装与替代方案
很多人用着用着就觉得 Notebook 的导航能力太弱。代码写了几十个单元格之后,往下翻全靠滚轮,找一个小标题要滑半天。最早我也不在乎这个,直到有一次在分享会上,现场演示的时候为了找一个画图函数,在全场注视下翻了大概二十秒,那感觉太尴尬了。从此我第一时间装目录插件。
经典 Notebook 时代,最常用的目录方案是 nbextensions 里的 Table of Contents 插件。安装步骤如下:
bash复制# 安装 jupyter_contrib_nbextensions
pip install jupyter_contrib_nbextensions
jupyter contrib nbextension install --user
装完启动 Notebook,在 Nbextensions 标签页里勾选 Table of Contents 即可,侧边栏就会出现可用的目录大纲。这个插件会根据 Markdown 单元格的标题级别自动生成目录,点击就能跳转。如果你不想装额外插件,还有更轻量的方式——用 Markdown 写 [[TOC]],渲染时也能生成一个简单的页内目录(需要 Markdown 扩展支持,默认不一定开启)。
不过说实话,现在更推荐直接用 JupyterLab。Lab 从 3.0 开始自带 Table of Contents 面板,打开左侧栏的目录图标,所有标题层级一目了然,点击跳转、拖动排序都支持,不用装任何额外扩展。从 Notebook 迁移到 Lab 的话,这个功能是最先让你感受到“值了”的一处。
bash复制# JupyterLab 启动方式
jupyter lab
2.2 文件管理与导入文件夹:别把时间耗在路径上
Notebook 做完之后经常会碰到一个问题:想把同目录下的数据文件导进来,但路径总是写不对。其实这背后是 Jupyter 的“当前工作目录”机制在作怪。
首先要明确:Notebook 里的当前目录,不是 .ipynb 文件所在的目录,而是启动 jupyter 命令时所在的目录。也就是说,如果你在 D:\workspace 下启动了 Jupyter,那么你的代码里 open('data.csv') 会去 D:\workspace 找,而不是 D:\workspace\project\ 去找。这一点坑过非常多新手。
解决路径问题的几个惯例做法:
python复制# 方法一:用 os.chdir 切成 notebook 所在目录
import os
os.chdir(os.path.dirname(os.path.abspath('__file__')))
# 方法二:直接把项目根目录手动加入路径,然后正常 import
import sys
sys.path.append('/path/to/your/project')
如果想彻底不用手写路径,那就是在启动 Jupyter 之前,先进到目标文件夹,再启动服务:
bash复制cd /d D:\workspace\your_project
jupyter notebook
还有个比较隐蔽的需求:怎么把本地文件夹整体导入 Jupyter。其实不需要导入,Jupyter 的文件浏览器天然就是看服务启动目录下所有文件的。如果你要上传大数据集,我建议直接拖拽上传而不是用代码,上传进度条会更直观。对于几十 GB 的文件,别走网页上传,直接用 pyftplib 或者共享目录挂载,网页上传大文件容易断,我没少踩这个坑。
3. 效率起飞:快捷键、魔术命令与内核管理
3.1 常用快捷键:让手不离开键盘
Notebook 有一个很受人喜欢的交互模式:命令行模式和编辑模式。在命令行模式下,你按的不是字符,而是操作指令。比如:
| 快捷键 | 作用 |
|---|---|
| Enter | 进入编辑模式 |
| Esc | 回到命令行模式 |
| A / B | 在上方/下方插入单元格 |
| M / Y | 转为 Markdown / Code 单元格 |
| D D | 删除单元格 |
| Shift + Enter | 运行当前单元格并跳到下一个 |
| Ctrl + Enter | 运行当前单元格,不跳转 |
| Alt + Enter | 运行并新建下方单元格 |
| Ctrl + Shift + P | 打开命令面板 |
用熟了之后,写代码基本就是 A、B、M、Y、Shift+Enter 这几个键来回切换,鼠标只会在点选单元格或查看结果的时候用到。JupyterLab 里这套快捷键默认兼容,不用重新学。
还有个小技巧,是我自己用了很久才发现的功能——Code 单元格里可以执行 Shell 命令,只要前面加个 !:
python复制!pip install requests
!ls
!python --version
这个在临时装包、查看系统信息时特别省事,不用专门开个终端窗口切来切去。
3.2 Magic 命令:Notebook 里被低估的“瑞士军刀”
Magic 命令算是 Notebook 里最有特色的功能,但大多数人只知道一个 %matplotlib inline,确实有点亏。我把日常使用频率最高的几个列一下:
%timeit 和 %%timeit:测试代码性能的标准姿势。我在评估一个算法能不能跑通大数据集时,通常先跑一段 %timeit 看看单次执行时间,再估算全量数据要跑多久。
python复制%timeit sum(range(1000000))
%%time:如果你不关心逐次差异,只关心这次运行整体耗时,用这个更直观。它会输出 Cell 的 CPU 时间和墙钟时间。
%run:让 Notebook 直接执行一个 Python 脚本。我在写爬虫或数据处理脚本时,会先用普通 .py 文件写好逻辑,再在 Notebook 里 %run my_script.py 来集成调用。这样既能保留 Notebook 的可视化交互,又不至于所有逻辑都堆在一个 .ipynb 文件里。
%debug:出现异常以后,输入 %debug 可以直接进入事后调试器。这个在函数调用栈特别深的时候很有用,可以快速检查各个局部变量的值。平时我是做完每个步骤,感觉可能有问题就随手加一个 %debug 试试。
%load_ext 和 %%writefile:前者用于加载扩展,后者可以把单元格内容写成一个 .py 文件。%%writefile 本质上是利用 Notebook 做代码生成器,我写小型爬虫脚本时经常先调通单元格,然后一键导出成 .py 文件跑 cron。
%store:跨 Notebook 共享变量。开了两个 Notebook 分别处理数据沉淀和可视化,用 %store 传递 DataFrame 名称,不用每次重新跑一遍数据预处理,省不少事。
python复制%store df_clean
# 在另一个 notebook 中
%store -r df_clean
3.3 内核管理:多环境切换不迷路
Notebook 默认用的内核是启动时那个环境里的 Python。但很多时候你需要切换环境,比如机器上既有 Python 3.8 的环境,又有 3.10 的环境;或者你在 conda 里建了 tf 环境、torch 环境,希望能在同一个 Notebook 界面里切换。
如果你在 conda 环境里装了 ipykernel,并且把这个环境注册成内核,就可以在 Notebook 右上角选择内核了:
bash复制conda activate myenv
pip install ipykernel
python -m ipykernel install --user --name myenv --display-name "Python (myenv)"
这里的 --name 是内核的内部名称,--display-name 是显示在下拉菜单里的名字。注册完成后,重启 Notebook 就能在下拉框中看到新内核。
还有一类很常见的需求:用 Jupyter 连接远程服务器上的内核(比如带 GPU 的机器)。做法是在远程启动 jupyter:jupyter notebook --no-browser --port=8889,然后本地通过 SSH 隧道连过去。这个操作在深度学习任务里几乎是标配,不过要注意开放防火墙端口,且务必设置密码或密钥访问,不留默认无密码的裸奔状态。
4. 一条龙工作流:从数据分析到成品输出
4.1 数据分析探索:用 Notebook 做记录型开发
数据探索阶段,其实很少有人会整理得干干净净。多数情况是不断地跑代码、看输出、画图、改参数,在一个 Notebook 里形成“思考痕迹”。这种习惯初期还好,时间一长,一个 Notebook 几百个单元格,前一步的输出被后面覆盖,找结论时特别痛苦。
我个人的解决方案是“分区写作”+“尽量使用 markdown 记录决策”。每个分析阶段开始前,先写一个 Markdown 标题和一段文字说明:这一步要看什么、假设是什么、预期结果是什么。跑完代码后,再更新这段 Markdown,把结论补上。这样 Notebook 成了一个真正的“交互式分析报告”,后续回溯或者给别人看,根本不用重新跑一遍代码就知道你当时做了什么。
有一个细节值得提一下:Notebook 做数据分析时,单元格的输出只保留最近一次运行的结果。如果你的分析依赖上一次的输出,比如你在某个单元格打印了一个变量的值,后面又用这个值做判断,建议把它显示在 Markdown 里,或者用 print 格式化输出,方便后续跟踪。
4.2 Jupyter Notebook 做自媒体:把代码变成内容
不少搜索热词里带着“如何使用notebook做自媒体”,这个想法我特别理解,因为 Notebook 本身就是一种“图文混排”的格式,非常适合做技术内容创作。我的做法是用它写文章底稿,再用 nbconvert 导出多种格式。
bash复制# 将 notebook 导出为 markdown
jupyter nbconvert --to markdown my_article.ipynb
# 导出为 HTML
jupyter nbconvert --to html my_article.ipynb
# 导出为 PDF(需要 latex,较少用)
jupyter nbconvert --to pdf my_article.ipynb
导出 Markdown 之后,图片会被自动引用到同目录下的文件夹,方便你直接贴到技术社区或者博客后台。如果直接发布 HTML,代码块的样式也够看,配合自定义 CSS 可以做到不错的效果。
这里有个建议:做自媒体内容的话,Notebook 更适合做“草稿+思路整理”。如果你想产出一个排版精致的成品,建议把文字和代码分离,用 Notebook 做代码演示,用文档编辑器做排版。
4.3 notebook 保活与批量执行:别让进程这么容易断
热词里出现了“魔搭社区notebook 保活”,虽然它特指的是某个平台上云端 Notebook 的防休眠技巧,但放到本地场景也有对应的问题——Notebook 进程如果被系统休眠、网络断开或者执行时间过长,客户端容易断开,重连后还可以继续执行,但如果是长期运行的任务,也会面临进程被杀。常见做法是改用 nohup 后台启动:
bash复制nohup jupyter notebook --port=8889 --allow-root &
这样即使关闭 SSH 终端,服务进程也能继续运行。云端 Notebook 的话,一般是通过定期发心跳请求来保活,我在本地没用过这种,但原理类似。
5. 高频故障排查:报错与异常处理实录
5.1 无法打开和运行代码:最常见的三类问题
“Jupyter Notebook 无法打开和运行代码”是热词里出现频次很高的一个问题,几乎每周都有人问我。归纳起来,问题集中在三个层面:
第一类:启动后浏览器直接白屏或没法自动打开
通常是因为浏览器兼容性或者端口被占用。解决办法:
bash复制# 指定端口启动
jupyter notebook --port=8890
# 如果默认浏览器打不开,手动复制浏览器地址
第二类:Notebook 能打开,但运行代码没输出或一直显示 In [*]
这基本是内核断连或卡死。优先检查终端窗口有没有报错。如果终端正常,在浏览器里 Kernel -> Restart & Clear Output 重新跑。如果还是卡住,一般是某个包层面死锁了,比如 matplotlib 后端不兼容、pandas 版本问题等。这时在 Notebook 里新建一个 Code 单元格,运行 import sys; print(sys.executable) 看看内核对应的 Python 路径对不对。
第三类:服务器连接失败,浏览器显示 connection refused
多数是后端进程没起来。如果你是在远程服务器上,在服务器上执行 jupyter notebook --ip=0.0.0.0 --port=8889,然后再本地连接。注意是否有防火墙拦截,远程访问必须设置密码。
还有一个我常遇到的坑:Notebook 启动之后,浏览器说是“没有权限访问”,但配置都改了,排查半天发现是配置文件里有语法错误,比如某个引号没闭合。这种情况终端启动时会有报错提示,但由于终端背在后面,新手根本不看。养成看终端的习惯,能少踩一半坑。
5.2 常见报错速查表
好些报错其实有固定解法,整理成一个速查表,可以随时翻:
| 报错现象 | 原因 | 解决办法 |
|---|---|---|
| 502: Couldn't connect to server | 内核崩溃或重启失败 | 查看终端输出,重启 Jupyter |
| 500: Internal Server Error | 代码或内核异常 | 看日志定位,Restart Kernel |
| Kernel died, restarting | 内核进程被杀 | 通常是内存不足,检查资源占用 |
| ModuleNotFoundError: No module named 'xxx' | 环境不对,包没装到当前内核里 | 用 !pip install xxx,或确认内核环境 |
| Traceback in jupyter_notebook_config.py line xx | 配置文件语法错误 | 用 python 命令单独执行配置文件检查语法 |
| TypeError: init() got an unexpected keyword argument | 版本不兼容 | 升级或降级相关包,重装 notebook |
其中配置文件那一条,热词里也提到了“file c:\users\administrator.jupyter\jupyter_notebook_config.py, line 1129”,这就是典型的配置文件语法错误或配置项失效。Jupyter 启动时会逐行执行配置脚本,哪行报错就直接给你抛出来。处理方法也简单:用编辑器打开文件,看提示的行号附近的配置项是否拼写正确,或者干脆把最近改动的配置项先注释掉,启动成功后再逐项放开。
5.3 老版本 bug 与兼容性处理
Notebook 每次升级之后,多少都会冒出些奇怪问题。我有一个体会:看到“Jupyter notebook 侧边如何显示标题总览”这类问题,很多时候是老版本里插件失效,因为 Jupyter 版本升级会把 nbextensions 插件机制改掉或禁用。解决办法是把 jupyter_contrib_nbextensions 和 nbextensions_configurator 都重装一遍、重新 enable。
要是你已经转用 JupyterLab,遇到插件不兼容,你可以用 --dev-mode 来启动,看看浏览器控制台输出什么,定位是哪个插件出了问题。大部分时候是某个扩展的 JS 报错,禁用掉再启用就好了。
6. 几个让工作习惯变好细节
6.1 输出太多,怎么清理显示
数据探索阶段,一个单元格可能输出一个超大的 DataFrame,后面滚动条都要拉很久。这种时候给输出收敛一下很有必要:
python复制# 只显示前 10 行
df.head(10)
# 用 pandas 配置限制显示行数和列数
import pandas as pd
pd.set_option('display.max_rows', 20)
pd.set_option('display.max_columns', 50)
# 如果输出实在太多,可以直接清空当前单元格的输出
另外在 JupyterLab 里,右键单元格选择 Clear Outputs 可以一次性清掉所有输出,这个在准备提交作业或发布内容前特别好用,能避免把几千行中间结果带出去。
6.2 误删单元格怎么救
Jupyter Notebook 的新手最容易犯的错:选中一个写了半小时的单元格,按了两下 D D 删得干干净净,然后瞬间傻眼。其实 Notebook 自带删除保护机制吗?没有,它默认就是直接删,没有回收站。我之前有次不小心删了三十多个单元格,最后只能从文件系统里手动恢复。
恢复的办法有两种:
- 如果 Notebook 文件本身还在,可以用编辑器的本地历史或版本控制(比如 git)找回之前的版本。
- 如果文件也保存过,但没有提交到 git,可以试试 JupyterLab 的右键 -> Local History,它会根据 autosave 保留最近的版本草稿。
所以重要节点一定要保存 .ipynb 文件,并且建议用 git 做版本管理。就算不 git,也建议定期做备份。作为一个踩过坑的人,我可以负责任地说:这绝对值得做。
6.3 打开速度慢,试试精简扩展
有些朋友的 Notebook 启动要 20 秒,鼠标点个单元格都要转圈。这种情况大概率是装的 nbextensions 太多了。每个插件都在页面里挂了自己的 JS 和 CSS,数量一多自然拖慢。我的做法是只保留最常用的三四个扩展,如 Table of Contents、ExecuteTime、Collapsible Headings,其余全部禁用。执行 jupyter nbextensions_configurator 就能看到启用清单,逐个关掉,然后重启,体感会好很多。
JupyterLab 的话,扩展管理在左侧 Extension Manager 面板里,同样不建议贪多。扩展与 JupyterLab 的主版本强相关,Lab 3.x 的扩展不能用在 Lab 4.x 上,升级主版本之前先确认重要扩展是否兼容,这算是我吃亏之前看过最多的坑。
7. 我在实际使用中的几点体会
最后说点真正使用之后的经验,不是文档里的东西。
第一,Notebook 和 Lab 不是替代关系。我现在日常主力是 Lab,写文章、做探索都是它。但某些旧项目用的是 Notebook 6.x 的界面,代码里有大量习惯性的快捷键,切换到 Lab 会有点不顺手。所以可以两个都装,按项目需求选择,不必非黑即白。
第二,不要把一个 Notebook 写得太长。理论上它能承载几百个单元格,但超过 100 个单元格以后,你基本就找不到上下文了,运行顺序也会变得混乱。更合理的做法是,把一个大的分析任务拆成几个 Notebook,中间用公共的中间结果文件(比如 parquet 或 csv)串联,每个 Notebook 只负责一个阶段。这样做既好维护,也方便复用。
第三,Notebook 的自动保存虽然靠谱,但重启之后不代表一切都能恢复。比如你定义了某些全局变量,但中间的单元格被清空了,内核重启后这些变量全部丢失,运行后面的代码就会直接 NameError。所以真正依赖的中间结果,要么写入文件,要么确保每次启动可以重新加载。
第四,配置文件的修改一定要一步一验。之前有个用户改密码配置时,在 jupyter_notebook_config.py 里同时改了三处,其中一处写错了,导致整个配置加载失败,服务直接起不来。后来我一律建议“每次只改一个配置项,保存后启动一次测试”,这样出了问题能立刻知道是哪项引起的。
如果你准备长期靠 Notebook 干活,那有一点要尽早适应:它的代码运行顺序天然非线性,这也意味着你写完一个 Notebook 后,最好从头到尾重新跑一遍,也就是 Kernel -> Restart & Run All,验证它是否可以完整复现。这不仅是为了自己,也是为了让看到你 Notebook 的人能顺利跑通。这个小习惯一旦养成,你的 Notebook 质量会直接上一个档位。
