1. 为什么我最终把 JupyterLab 当作日常主力,而不是 Jupyter Notebook
先说一个可能很多人都有同感的经历:最早接触 Jupyter 生态时,我用的还是老版的 Jupyter Notebook。那时觉得它已经够好了——能写代码、能跑结果、能插 Markdown 说明,做一个数据分析任务绰绰有余。但用着用着,问题就来了:多开几个 notebook 之后浏览器标签页密密麻麻;想在同一个项目里对比两份实验数据,得在两个页面之间来回跳;想打开一个终端跑点辅助命令,还得分神去切到系统终端窗口。
后来我转到 JupyterLab,这个困扰才算真正解决。JupyterLab 可以理解为 Notebook 的"完全体"——它不是一个简单的升级版,而是在同一个界面里把 notebook、终端、文本编辑器、文件管理、甚至数据查看器全部整合到一起。你在左边栏能看到整个项目目录,中间可以并排打开多个 notebook,右边还能挂一个终端窗口实时跑命令。这种"一个工作台搞定所有事"的体验,一旦习惯就回不去了。
不过我也得说句公道话:Jupyter Notebook 虽然看起来"老",但它依然有不可替代的场景。比如很多教程、教材、线上课程还在用 Notebook 格式,你跟着做作业时就必须用 Notebook 打开;又比如你只想快速验证一小段代码,不想开一个复杂的 IDE,Notebook 那种"轻装上阵"的感觉反而更舒服。更别说 Jupyter Notebook 的插件生态(比如 nbextensions)在某些功能上至今仍然比 JupyterLab 成熟。
Voilà 则是另一个方向的延伸。它把 notebook 里的代码、输出和交互控件变成独立的 Web 应用,读者看到的是干净的界面,不需要看到背后的代码。换句话说,JupyterLab 适合你自己干活,Jupyter Notebook 适合跟随教程学习,而 Voilà 适合把你做好的东西"发布"给不懂代码的人看。这三者不是取代关系,而是分工关系。
这篇指南的目标很具体:我会从安装开始,把三者的关系理清楚,再把实际使用中最容易踩的坑和最少有人讲的细节一并交代。无论你是第一次接触 Jupyter 生态的新手,还是已经用了 Notebook 很久、正在犹豫要不要转向 JupyterLab 的老用户,这篇内容都能帮你节省不少试错时间。文章里的命令和步骤都是我在 Windows、macOS 和 Linux 三套环境上实测过的,你照着操作基本不会翻车。
2. 安装前的关键选择:到底用 pip 还是 Anaconda
2.1 两种安装方式的核心差异
聊安装之前,必须先决定一件事:你用 pip 还是 Anaconda。这个选择会影响你后面的一切操作,所以值得花点篇幅讲清楚。
最简单的安装方式当然是 pip。只要你的电脑上已经有 Python 环境(比如 Python 3.8 以上版本),一条命令就能装好 JupyterLab:
pip install jupyterlab如果你是老派的 Notebook 使用者,装这个:
pip install notebook两个都想装也可以:
pip install jupyterlab notebook但 pip 方式有一个隐藏问题:它会把你现在的 Python 环境搞得比较"乱"。Jupyter 生态依赖一大堆底层库(比如 tornado、pyzmq、nbformat、traitlets),这些库的版本如果和你现有的项目冲突,pip 通常会直接覆盖升级,导致其他项目突然跑不起来。我有一次就是在某个环境里升级了 Jupyter 之后,发现 Django 项目启动时报错,查了半天才找到原因是某个底层依赖被悄悄换了版本。
Anaconda 则完全不同。它内置了 Python 解释器、常用科学计算库(NumPy、Pandas、Matplotlib、SciPy 等),还自带 conda 作为包管理器。你装好 Anaconda 之后,JupyterLab 和 Notebook 一般都已经预装好了,直接用即可。就算要自己装,也是用 conda 建一个独立环境,互不干扰。
如果你问我到底选哪个,我的建议很简单:
- 新手、主要做数据分析/机器学习、不想折腾环境:直接用 Anaconda。
- 已经有较复杂的 Python 环境、只是偶尔写写 notebook、对依赖隔离很敏感:用 pip,最好配虚拟环境。
- 已经熟悉 conda 那一套的:conda 创建独立环境装 JupyterLab,是目前最省心的组合。
2.2 用 Anaconda 安装时的实操要点
Anaconda 的安装过程本身没什么好讲的,无非是去官网下载对应系统的安装包,一路下一步。但有三个细节是我实际安装过很多次之后才总结出来的:
第一,安装时如果遇到"Add Anaconda3 to my PATH environment variable"这个选项,我的建议是:不要勾选。很多人图方便会勾上,结果后面使用中出现 conda 命令和系统原有 Python 冲突的概率非常高。正确做法是装完之后用 Anaconda Prompt(Windows)或终端(macOS/Linux)进入 conda 环境,再执行命令。
第二,安装路径不要带中文和空格。Conda 对路径的解析有时候很敏感,路径里有空格还好说,有中文就很容易出现莫名奇妙的编码错误。
第三,Anaconda 默认自带的 Jupyter 版本可能不是最新的。如果你需要最新版本,不要直接在 base 环境里升级,建议创建一个独立环境:
conda create -n jupyter-env python=3.11 conda activate jupyter-env conda install jupyterlab notebook这样做的最大好处是:这个环境专门服务 Jupyter,无论怎么折腾都不会污染你的 base 环境。我平时做数据分析就用这个独立环境,做其他开发时切换回 base 或其他环境,互不干扰。
2.3 pip 安装的进阶操作:虚拟环境隔离
如果你选择 pip,我强烈建议你先创建一个虚拟环境。Python 自带的 venv 就够了,不用额外装 virtualenv:
python -m venv jupyter-venvWindows 下激活:
jupyter-venv\Scripts\activatemacOS/Linux 下激活:
source jupyter-venv/bin/activate然后在这个虚拟环境里安装:
pip install --upgrade pip pip install jupyterlab notebook这样一来,你所有的 Jupyter 相关包都待在 jupyter-venv 这个独立目录里。即使某天你把整个环境删掉重来,也不会影响系统的 Python。我有一次在项目里需要安装一个旧版本的 pandas,直接在这个独立环境里随便装,完全不担心影响其他项目,这种安心感是全局安装永远给不了的。
注意:不管用哪种方式安装,装完之后建议执行一次
jupyter --version和jupyter lab --version,确认版本号和可执行文件路径。如果输出里出现"command not found"或"不是内部或外部命令",多半是 PATH 没有配好,优先检查安装方式是不是符合上面说的规则。
3. JupyterLab 的启动、界面布局与日常使用流程
3.1 启动方式与常见参数
安装完成后,启动 JupyterLab 非常简单。在终端(或者 Anaconda Prompt、激活后的虚拟环境终端)里执行:
jupyter lab执行完它会自动打开浏览器,并访问类似http://localhost:8888的地址。如果你的电脑没有默认浏览器,或者你想在指定浏览器里打开,可以加参数:
jupyter lab --browser=firefox还有一些参数在实际使用中很有用。比如,修改启动端口:
jupyter lab --port=9999如果你在远程服务器上跑 JupyterLab,想从本地浏览器访问,需要加上:
jupyter lab --ip=0.0.0.0 --no-browser然后本地浏览器访问http://服务器IP:8888。这里有个安全提醒:远程访问时一定要设置密码,否则等于把服务器裸奔在公网。设置密码的方式:
jupyter server password执行后按提示输入两次密码即可。它会生成一个哈希密码写入配置文件,之后访问就需要认证了。我在实际部署中遇到过不少人忽略这一步,结果服务器被扫描到后被人拿去跑挖矿程序,切记切记。
3.2 界面布局:每个区域是干嘛的
第一次打开 JupyterLab,你可能会觉得界面比 Notebook 复杂不少。其实它的布局逻辑非常清晰,从左到右主要是三块:
左侧是文件浏览器(File Browser),默认显示当前工作目录。你可以在这里新建文件夹、上传文件、新建 notebook、打开任意文本文件或图片。右键还能看到"Open in Terminal",直接在子目录打开终端,这个功能在 Notebook 里是做不到的。
中间是主工作区(Main Work Area),你可以把任意多个 notebook、终端、文本文件、图片拖到这里,它们会以标签页的形式排列。最常用的操作是:把两个 notebook 并排拖动到左右分栏,这样就能实时对比两份实验结果。
右侧是侧边栏(Right Sidebar),默认显示"Properties"(属性)面板,可以查看当前 notebook 的 kernel、文件大小、最后保存时间等信息。此外还可以在这里打开"Running Terminals and Kernels"(运行中的终端和内核)面板,方便你批量管理一堆会话。
底部有一个状态栏,显示当前 notebook 的内核状态(idle/ busy)、行号、内存使用等。我在调试长任务时经常盯着这个状态栏,如果显示 busy 就知道代码还在跑,如果变回 idle 就说明跑完了。
3.3 日常使用流程:从新建到导出的完整闭环
我日常的使用流程一般是这样:在左侧文件浏览器里选中目标目录,点右键 → New → Notebook,选择 Python 3 内核,一个干净的 notebook 就建好了。
在 notebook 里写代码时,JupyterLab 的自动补全比 Notebook 强不少。默认按 Tab 键就能弹出补全列表,并且很多第三方库的类型信息也能正确解析。我在 Notebook 里经常觉得补全不够聪明,但在 JupyterLab 里明显准确很多。
写完后,我想把结果分享给同事看,通常会用"Export"功能。JupyterLab 支持导出为 HTML、Markdown、PDF 等格式。路径在菜单栏 File → Export Notebook As。这里有个小坑:导出 PDF 时如果系统里没有安装 LaTeX 引擎,会直接报错。我自己一般不加 LaTeX,而是先导出为 HTML,再通过浏览器打印成 PDF,效果差不多且少踩很多坑。
如果你用的是 Jupyter Notebook(也就是传统界面),启动命令是:
jupyter notebook打开后的界面就简单多了:一个文件列表页面,点击 notebook 文件即可开始编辑。它没有 JupyterLab 那样的多标签、分栏和终端整合,但对于单纯写代码和跟随教程学习,完全够用。我至今仍保留 Notebook 的一个原因是:某些老项目里用了 nbextensions 的扩展(比如 table of contents、代码折叠),这些扩展在 JupyterLab 里还没有完全的替代品。
3.4 内核(Kernel)的概念:为什么重要
不管你用 JupyterLab 还是 Notebook,都会频繁听到一个词:Kernel(内核)。通俗点说,Kernel 是真正执行代码的后台进程,notebook 界面只是你写代码和看结果的前端。
每个 notebook 右上角会显示当前使用的 Kernel 名称,比如 "Python 3 (ipykernel)"。如果你安装了多个 Python 环境,会发现每个环境可以注册自己的 Kernel,在切换环境后 notebook 依然能认出它。
我在多个环境之间切换时,经常用到一个技巧:把指定环境注册为 Jupyter Kernel。进入目标环境后执行:
python -m ipykernel install --user --name my-env --display-name "My Env"这样启动 Jupyter 后,新建 notebook 时就能在 Kernel 列表中看到 "My Env" 选项。有了这个技巧,我在一个 JupyterLab 里就能同时管理多个不同环境的 notebook,而不用反复切换终端。我强烈建议每个用多环境的读者都掌握这个命令。
另外,如果一个 notebook 长时间无响应,可以在菜单栏 Kernel → Restart Kernel 里重启内核,内存就释放了。但注意重启内核会清空所有变量,代码重新执行前那些中间结果就全没了,所以重要数据一定要及时保存到文件。
4. Voilà 的安装与 notebook 应用化实操
4.1 Voilà 到底解决什么问题
我最早听说 Voilà 是在一次内部工具分享会上。当时同事把一个数据筛选的 notebook 通过 Voilà 发布成了一个网页应用,里面有一个下拉框、一个滑块,拖一拖就能实时看到筛选后的图表。整个交互过程完全不需要看到代码,发给业务部门的同事,他们直接在浏览器里操作就行。当时给我的感觉是:这不就是把 notebook 变成"产品"了吗?
后来我自己做数据分析,经常遇到一个尴尬:分析做完了,图表也画好了,但怎么分享给不会用 Jupyter 的领导?直接发 ipynb 文件,对方打不开也看不懂;截图发过去,又没法交互。Voilà 就是解决这个问题的:它读取一个 notebook,把里面的代码执行结果渲染成一个干净、独立的网页应用,并且支持 ipywidgets 交互控件。
所以,Voilà 适合的场景是:你想把一个 notebook 变成"工具"发给别人用,把输入控件和输出展示封装成界面,隐藏背后的代码逻辑。
4.2 安装 Voilà 的完整步骤
安装 Voilà 非常简单,基于你已经装好 JupyterLab 的前提下:
pip install voila如果你想用 conda,也可以:
conda install -c conda-forge voila启动方式有两种。第一种是直接在终端运行:
voila它会扫描当前目录下的所有 notebook 文件,生成一个文件列表页面,点击任意 notebook 就会以 Voilà 方式渲染。
第二种更为常用:如果你正在 JupyterLab 中编辑 notebook,点击工具栏上的 Voilà 图标(一个波浪线组成的图标),就会在新标签页中打开该 notebook 的 Voilà 渲染结果。如果你在界面上找不到这个图标,可能需要先启用 Voilà 的 JupyterLab 扩展:
jupyter labextension install @jupyter-voila/jupyterlab-preview不过现在大多数版本安装voila时会自动安装配套扩展,如果你装完发现没图标,再执行上面这条命令即可。
4.3 如何把 notebook 调整成适合 Voilà 展示的形态
Voilà 默认会隐藏代码单元格,只展示输出和交互控件。这带来一个微妙的问题:如果你的 notebook 没有合理组织,直接发布出来会比较乱。我总结了一套适合 Voilà 的 notebook 组织方法:
第一步,把代码按逻辑分段。最理想的结构是:最上方几个单元格导入库和加载数据,中间的单元格定义处理函数,最后一部分放交互控件和图表。这样 Voilà 按顺序从上往下执行,每一段输出都会出现在对应的位置。
第二步,用 Widgets 构建交互控件。一个典型的滑块加图表示例:
import ipywidgets as widgets from IPython.display import display import matplotlib.pyplot as plt import numpy as np # 创建一个滑块 slider = widgets.IntSlider(value=50, min=1, max=100, description='点数:') # 画出随滑块变化的图 def plot_points(count): plt.figure(figsize=(6, 4)) x = np.random.rand(count) y = np.random.rand(count) plt.scatter(x, y) plt.title(f'随机散点图({count} 个点)') plt.show() # 通过 interact 将滑块和画图函数绑定 widgets.interact(plot_points, count=slider)在 notebook 里运行这个单元格,你会看到滑块和图表同时出现。Voilà 会自动把这种交互原样带到网页里,读者拉动滑块,图表实时变化,完全不需要接触代码。
第三步,隐藏不必要的代码。Voilà 默认隐藏代码,但你还可以通过 cell tag 的方式更精细地控制显示。具体做法是在 notebook 的单元格上添加 taghide_input,这样即使某些单元格需要显示代码,也能通过 tag 隐藏。JupyterLab 中给单元格添加 tag 的方法是:选中单元格 → 右侧属性面板 → Add Tag。
4.4 发布时的路径与参数注意
启动 Voilà 时有一些参数值得提前知道。比如,指定端口和 IP:
voila --port=8866 --ip=0.0.0.0 --no-browser这在部署到服务器时非常常用,能让团队其他成员通过浏览器访问。还有:
voila --template=gridstack这个参数会启用 gridstack 模板,把多个输出单元格以卡片布局排列,适合做一个"仪表盘"风格的多图表页面。我试过这个模板,视觉效果比默认模板好不少,尤其是同时展示多张图表的场景下。
如果你不想让所有人进入 Voilà 后看到文件列表,想直接进入指定 notebook,可以这样:
voila my_notebook.ipynb这样启动后会直接渲染指定的 notebook,适合作为一个独立应用的入口。部署时我还会配合反向代理(nginx)把它映射到某个子路径,不过那是后话,普通使用不需要关心。
4.5 Voilà 与 Streamlit / Dash 的取舍
写到这里我想插一句实话:不是所有 notebook 应用化场景都适合 Voilà。如果只是做一个简单的数据展示页,Voilà 够用;但如果你想做一个更复杂的 Web 应用,比如多页面路由、用户登录、表单提交后写数据库,Voilà 会比较吃力。这时我更推荐 Streamlit 或 Dash。
不过 Voilà 有一个独特优势:它基于 Jupyter 生态,和学习成本几乎为零。你已经会用 notebook 写代码,就相当于已经会写 Voilà 应用。Streamlit 和 Dash 则要求你去学一套新的 API 和状态管理逻辑。所以,如果你的需求是"快速把分析结果变成可交互的网页分享给别人",Voilà 是性价比最高的选择;如果未来要做的产品更复杂,届时再迁移到 Streamlit 也不迟。
5. 三者的关系与实战中的协同用法
5.1 一个项目里让三件套各司其职
很多人以为 JupyterLab、Notebook 和 Voilà 是三条平行线,其实在一个完整项目中,它们可以配合得非常默契。我这里用一个实际项目来演示:假设我要做一个"销售数据的月度异常检测"分析。
第一步,我会在 JupyterLab 里创建项目目录,录入数据文件。典型操作是:打开 JupyterLab → 左侧 File Browser 导航到项目文件夹 → 上传 CSV 数据文件。接着新建一个 notebook,开始探索性数据分析:查看数据量、缺失值情况、分布特征。这段过程我会频繁使用 JupyterLab 的终端功能,直接在终端里跑 pandas 的批处理脚本,再回到 notebook 里做可视化。
第二步,分析思路定型后,我可能把这个 notebook 按 Voilà 的要求重新组织,加上滑块、下拉框等交互控件。比如加上一个月份选择器,观众可以切换月份查看对应的销售额曲线;加上一个异常阈值滑块,拖动时可以标记出高于阈值的点。
第三步,我把这个 notebook 保存为sales_dashboard.ipynb,然后通过 Voilà 发布。业务同事打开网页后直接操作,完全不需要知道我背后用了什么模型。整个过程,JupyterLab 是我的开发环境,Notebook 是分析过程记录,Voilà 则是最终交付物——三者不是互相替代,而是串成了一条流水线。
5.2 实际部署时需要注意的资源与安全问题
把 Voilà 部署到服务器上时,有几个细节我踩过坑,拿出来说一下。
第一,Voilà 本质上是在启动一个 Jupyter 服务。如果你在服务器上以voila命令启动,它默认会在你当前用户的家目录下寻找 notebook。如果你的数据文件在另一个目录,建议在启动前先cd到目标目录,否则渲染时会找不到相对路径的文件。
第二,Voilà 的每个会话都会执行一次 notebook 中的代码。如果 notebook 里有耗时的数据加载或模型训练步骤,每打开一个会话就重新跑一次,很容易把服务器内存打满。我的做法是尽量把费时的数据处理结果提前缓存成文件(比如 CSV、parquet、pickle),Voilà 渲染时只做读取和可视化,避免每次打开页面都跑一遍全量计算。
第三,网络环境下的安全。Voilà 默认自带 token 认证,启动时终端会打印一个访问 URL,里面包含token=xxx。如果你把这个 URL 发给别人,对方就能访问。如果你想把 Voilà 挂在公网长期运行,建议用反向代理并将 Voilà 绑定到127.0.0.1,然后在 nginx 层面加 Basic Auth 或统一登录认证,这样相对更稳妥。
5.3 Notebook 与 JupyterLab 并存的日常习惯
很多人会纠结要不要"彻底用 JupyterLab 替换 Notebook"。我的经验是:不要非此即彼。JupyterLab 和 Notebook 可以并存,而且并存时的体验更好,因为你可以在 JupyterLab 里随时打开任意旧版 Notebook 格式的文件。JupyterLab 本身就能打开.ipynb文件,而且渲染方式完全兼容,所以不存在"老文件打不开"的问题。
更值得一提的是,JupyterLab 3.x 之后默认支持从界面查看 ipynb 文件的 JSON 源码(右键 → Open With → JSON Editor),这个功能对排查文件损坏问题很有用。如果某个 notebook 文件因为意外断电损坏,用 JSON 编辑器打开通常还能恢复大部分内容。
所以我现在的日常习惯是:默认所有分析和开发都在 JupyterLab 里完成,遇到需要跟随网上的教程操作时,如果教程明确指定用 Jupyter Notebook,我就直接打开 Notebook;如果教程支持 JupyterLab,我会直接用 JupyterLab 打开同一个文件。两个工具之间切换非常丝滑,因为它们都遵循同一个.ipynb文件格式,内核配置也完全互通。
6. 高频报错、安装冲突与"一定绕开"的几个坑
6.1 启动时提示找不到 jupyter 命令
这是我在帮别人排查时遇到最多的一个问题。明明装的时候没报错,但执行jupyter lab就是提示"command not found"或"不是内部或外部命令"。
根本原因通常是 PATH 没有包含 Jupyter 可执行文件的目录。以 pip 安装为例,Jupyter 的可执行文件一般装在 Python 的 Scripts 目录(Windows)或 bin 目录(Linux/macOS)。如果这个目录不在 PATH 里,命令就找不到。
解决思路有两种。一是把对应目录加入 PATH;二是直接用模块方式启动,绕过 PATH 问题:
python -m jupyterlab或者:
python -m jupyter lab通过python -m的方式启动,一定会使用当前 Python 环境里的 Jupyter,不会受到 PATH 混乱的影响。我在多个服务器上都用这个方式,基本不会出问题。
6.2 区别"安装位置不一致"造成的内核混乱
你可能会遇到这样一种情况:在终端里能正常进入 Python 并 import pandas,但打开 JupyterLab 之后,notebook 里import pandas却报 ModuleNotFoundError。这通常是内核(Kernel)对应的 Python 解释器和当前终端激活的 Python 不是同一个。
我以前在这上面的教训比较深。有一次我在 base 环境装了 pandas,然后创建了一个新 conda 环境,激活新环境后启动了 JupyterLab,结果 notebook 使用的还是 base 的 ipykernel——因为我没有在新环境里单独注册 kernel,JupyterLab 默认读取的是先前注册过的。后来我学会了一个习惯:在新环境里固定执行一次:
python -m ipykernel install --user --name my-newname --display-name "My NewName"确保 JupyterLab 里的 Kernel 列表中出现"My NewName"这个选项,再启动 notebook 时手动选择它,就彻底解决了这个混乱。
6.3 Voilà 渲染时图表不显示的常见原因
Voilà 渲染时最常见的坑是:notebook 里能正常显示的 matplotlib 图表,Voilà 页面里什么都不显示。
原因之一是 matplotlib 默认的输出后端和 Voilà 不兼容。解决办法是在 notebook 开头执行:
%matplotlib inline把这行加进去之后,matplotlib 的图表就会以内嵌形式输出,Voilà 也能正常展示。如果你用了 seaborn,它其实底层还是 matplotlib,所以%matplotlib inline同样适用。
另一个原因是代码单元格里用了plt.show(),这本身没问题,但有些版本的 Voilà 对动态输出的刷新有延迟。建议把plt.show()放在单元格最后,不要和大量 print 语句混在一起,避免渲染时的优先级冲突。
6.4 pip 安装时的依赖冲突处理建议
装了 JupyterLab 之后,再装其他数据分析库时偶尔会提示依赖冲突。这种情况下我一般不建议强拆强装。优先做法是用虚拟环境隔离,或直接改用 conda 环境。Conda 的依赖解析器比 pip 强不少,它能自动帮你挑一套互不冲突的包版本。
如果你已经在 conda 环境里,可以执行:
conda install jupyterlab notebook voilaConda 会尝试找到兼容的组合。实在冲突且无法解决时,再手动指定版本安装。比如:
pip install voila==0.5.0这种"手动锁版本"的方式会让环境更可控,但也意味着后续升级时可能还有冲突,所以我始终强调环境隔离优先于强行统一版本。
6.5 Windows 用户特有的坑:编码与路径问题
Windows 上使用 Jupyter 时,我遇到最多的是路径编码问题。如果你的用户名或项目路径包含中文,有些库在读写文件时可能报 UnicodeDecodeError 或 FileNotFoundError。这个问题在 Jupyter 自身处理得还行,但在某些扩展库(尤其是老版本 Pandas)身上比较明显。
我的建议是:项目目录尽量用英文,文件名也尽量不用中文。这不是什么高科技,但确实能省掉很多莫名其妙的报错。如果你接手了一个已存在中文路径的项目,可以在 notebook 开头设置:
import sys import io sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')这样可以缓解一部分中文编码问题,但最好的解决方案还是从源头规避。
7. 扩展配置:token、密码、远程访问与常用插件
7.1 登录安全配置:token 与密码
JupyterLab 和 Notebook 默认启动时会生成一个 token,URL 里会显示。这个 token 相当于你访问服务的凭证。如果你觉得每次复制 URL 带 token 太麻烦,可以设置固定密码。
最推荐的方式还是在终端里执行:
jupyter server password输入两遍密码后,它会自动写入配置文件~/.jupyter/jupyter_server_config.json。之后启动 JupyterLab 访问时,就可以用这个密码登录,而不需要 URL 里带 token。
如果你想手动配置自定义端口、IP、是否允许远程访问,可以生成配置文件再修改:
jupyter server --generate-config生成的文件位于~/.jupyter/jupyter_server_config.py。打开后找到对应的配置项修改即可。常用配置通常包括:
c.ServerApp.ip = '0.0.0.0' c.ServerApp.port = 8888 c.ServerApp.open_browser = False c.ServerApp.allow_remote_access = True这里我提醒一下:allow_remote_access = True意味着可以从外部访问,如果是在敏感网络或公网环境,一定要配上密码,并且最好用防火墙把端口限定在内网可访问。
7.2 常用插件:我实际在用的几款
JupyterLab 的扩展机制让它比 Notebook 更灵活。插件安装方式很简单,在 JupyterLab 界面里进入 Extension Manager,搜索插件名称,点 Install 即可。
我实际用下来觉得值得装的插件有这些:
- Table of Contents:自动生成 notebook 标题目录,长文档导航神器。
- jupyterlab-git:在界面里直接进行 Git 操作,查看 diff、提交和推送,方便到不用开命令行。
- jupyterlab-spreadsheet:在 JupyterLab 里直接预览 CSV 文件,双击就能看到表格,不用每次都用 pandas 读一遍。
- @jupyterlab/toc:左侧目录树,配合长 notebook 使用体验极佳。
- jupyterlab-variableinspector:边写代码边看当前环境里所有变量的值,调试时会省很多事。
Notebook 那边也有不少经典扩展,比如 nbextensions 里的 Table of Contents、Collapsible Headings、Codefolding。但这些插件的安装方式(使用 pip 安装jupyter_contrib_nbextensions后启用)比较折腾,而且和 JupyterLab 的扩展机制完全不同。所以我建议新用户直接拥抱 JupyterLab 的扩展生态即可,不必再花时间折腾老插件。
7.3 远程访问与反向代理:更优雅的部署方式
如果你在云服务器上使用 Jupyter 生态,除了直接在公网监听端口之外,我更推荐的部署方式是用反向代理。以 nginx 为例,可以这样配置一个子路径代理:
location /jupyter/ { proxy_pass http://127.0.0.1:8888/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }注意 JupyterLab 使用 WebSocket 进行实时通信,所以必须配置Upgrade和Connection头,否则前端可能出现"connection closed"的报错。
这种部署的好处是:你可以通过https://域名/jupyter/统一入口访问,并且可以在 nginx 层做访问控制、配置 SSL、把多个服务(如 JupyterLab 和 Voilà)映射到不同路径,管理起来更规范。如果你前面已经设置了 Jupyter 密码,外部访问的安全性就有了双重保障。
8. 从 notebook 迁移到 JupyterLab:我给你的平滑转型建议
8.1 别着急切环境,先从"混用"开始
不少朋友问我:要不要把手头所有 Notebook 项目都迁到 JupyterLab?我的回答是:不用着急,先从混用开始。
JupyterLab 打开.ipynb文件完全兼容旧格式,你直接拿 JupyterLab 打开原本在 Notebook 里写的文件,代码和输出都会原样显示。早期你不需要做任何迁移工作,只需要在日常操作中慢慢增加 JupyterLab 的使用比例:新建的项目优先在 JupyterLab 里做,只有打开旧的、依赖老插件的文件时才切回 Notebook。
我还建议你把平时常用的命令记下来,比如jupyter lab、jupyter notebook、jupyter server password、python -m ipykernel install以及voila。时间久了,你会形成一种肌肉记忆:需要开发环境时打开 JupyterLab,需要快速测试时打开 Notebook,需要分享交付时跑 Voilà。三者随时可以切换,不存在"只能选一个"的问题。
8.2 文件整理与目录结构的建议
Jupyter 生态的项目目录最好一开始就规划好。我自己的典型结构是这样的:
project/ ├── data/ │ ├── raw/ │ └── processed/ ├── notebooks/ │ ├── 01_explore.ipynb │ ├── 02_model.ipynb │ └── dashboard.ipynb ├── scripts/ │ ├── preprocess.py │ └── utils.py ├── output/ │ ├── figures/ │ └── reports/ └── README.md这样的好处是:Voilà 发布时只需要指定notebooks/dashboard.ipynb,数据路径统一从data/读取,不会出现"代码在 notebook 里能跑,在 Voilà 里找不到文件"的悲剧。脚本和 notebook 分离,也让项目更容易回溯和维护。
8.3 备份与版本管理
Jupyter notebook 文件是 JSON 格式,每次保存都会生成一个快照。但多人协作或自己长期迭代时,强烈建议用 Git 做版本管理。你可以在 JupyterLab 的终端里对项目目录执行git init,然后配合前面提到的 jupyterlab-git 插件,在界面里直接提交。这样每次改动都有历史,随时可以回退。
另外要提醒的是:.ipynb文件里会保存执行输出,输出里如果包含了大量图片,会让 Git diff 变得非常难读。如果团队协作严格,建议在 Git 客户端里启用nbstripout工具,在提交前剥离输出,只保留代码和 markdown,能显著减小仓库体积,也让代码审查更聚焦。我自己的习惯是:本地保留完整输出,提交到远程仓库时用nbstripout清理,需要展示结果时再通过 Voilà 生成网页给最终受众。
9. 个人使用体会与下一步可以尝试的方向
如果让我用一个比喻来总结 JupyterLab、Notebook 和 Voilà 的关系:Notebook 是厨房里的炒锅,JupyterLab 是整间厨房,Voilà 则是把做好的菜端到餐厅给客人品尝。这三件事在不同阶段出现,解决的是不同层次的问题,它们之间并不冲突,反而是我目前见过的最有效率的数据工作流之一。
最后分享一个我最近在尝试的方向:把 Voilà 发布的应用和定时任务结合起来。比如用 cron 在每天凌晨自动跑数据更新脚本,输出最新的分析结果到output/目录,Voilà 每次打开时不重新计算,而是读取已经刷新好的数据文件。这样一来,团队每天打开应用看到的都是昨天的数据,而服务器资源消耗几乎为零。如果你已经完成了本文里的安装和使用流程,我很建议你往这个方向再走一步——它会让你的数据产品从"能用"进化到"真正能持续运行"。
希望这篇东西对你的 Jupyter 之路有实实在在的帮助。遇到具体报错时,优先回看环境隔离、内核选择、文件路径这几个最容易被忽视的环节,多数问题都能在那里找到答案。