Jupyter Notebook 这个名字,做数据分析、跑模型、写教学代码的人应该都不陌生。但很多人装好之后都在犯一个极其隐蔽的错:每次双击图标启动,Notebook 里的文件全都在系统默认路径下,你自己的项目文件夹却怎么都找不到。你只能灰溜溜地一次次用文件菜单里的"打开"去翻目录,甚至有人被逼到直接在默认目录里裸奔式建了一堆乱八七糟的笔记本,时间一长全乱了。这篇文章要解决的就是这个事:怎么让 Jupyter Notebook 在你指定的文件夹下干净利落地运行,文件保存、加载都锁定在那个目录里。我会把命令行、Anaconda Navigator、改配置文件、定制快捷方式这几条路都走一遍,顺便把启动不了、路径改了不生效、路径带中文报错这些高频坑全踩平。无论你刚装好 Jupyter Notebook,还是已经在默认路径里挣扎了一段时间,这套内容都能直接用上。
1. 为什么必须在指定文件夹运行 Jupyter Notebook
1.1 默认路径带来的痛点
Jupyter Notebook 的核心工作单元是"笔记本文件",也就是 .ipynb 文件。你每写一个分析、跑一个可视化、存一套实验结果,都会落成一个 .ipynb 文件。问题恰恰出在这里:Jupyter 启动时如果没有明确指定目录,它就会跑去用用户主目录(在 Windows 上一般是 C:\Users\你的用户名,在 macOS/Linux 上是 /home/你的用户名)作为默认根目录。
这会造成三种非常具体的麻烦。第一,文件管理一团糟。你三个项目、五门课、两个工作上用的笔记本全都混在主目录里,找文件靠滚动条,命名只能靠"最终版""最终版2""真的最终版"来续命。第二,相对路径全部失效。很多人在代码里写pd.read_csv('data.csv')这样的相对路径,以为只要数据文件跟笔记本在同一个文件夹就行。但 Jupyter 的内核工作目录跟 Notebook 文件所在的目录是两回事,你在默认路径启动时,相对路径的基准点是主目录,而不是你的项目目录,于是data.csv怎么都找不到,报FileNotFoundError,一个无比常见且让人抓狂的错误。第三,清理和迁移困难。主目录里堆满了各种 .ipynb 和自动生成的 .ipynb_checkpoints 文件夹,你要备份一个项目,得满世界去挑文件。
这里我要把原理讲透:Jupyter Notebook 启动时,会以一个"根目录"(root directory)来定位你的工作区,并且文件树里能打开的所有笔记本,都必须是这个根目录或它的子目录里的文件。你指定了文件夹,工作区才真正属于你;你不用指定,那根目录就是你的用户主目录,你所有的笔记本都算"寄放"在那儿,数据文件一律要从主目录出发去找,不出问题才怪。
1.2 指定文件夹运行的本质原理
真正弄懂"在指定文件夹运行"是什么操作,你会突然觉得很多教程讲得云里雾里,其实就是四件事:改当前工作目录、启动 Jupyter 进程、让 Jupyter 的根目录指向这个目录、让内核的工作目录同步指向这里。命令行里的做法就是先cd到那个目录,再运行jupyter notebook,本质是让 Jupyter 子进程继承了当前 shell 的路径作为它的根目录;改配置文件的做法是把根目录写死在配置里,不管从哪里启动都锁住;快捷方式的做法是把路径作为启动参数直接传给 Jupyter。
这三种思路各自对应一个真实场景。命令行适合你随手要开一个新项目,临时性强;改配置适合有固定工作目录、天天就在那一个目录里干活的人;快捷方式适合 Windows 下双链双击党,想给每个项目做一个专属的启动图标。理解了这套底层逻辑,后面你无论选哪种方案,都不会在"改了配置为何没生效"或者"明明 cd 了却又跳回默认目录"这种问题上耗费太多时间。
2. 准备工作:安装与基础环境检查
2.1 三种安装方式怎么选
在聊指定文件夹之前,得先把"你在用哪种 Jupyter"这件事搞清楚,因为不同安装方式对应不同的启动入口和目录修改方式。
第一种是用 Anaconda 安装的。这也是绝大多数人最省心的选择,Anaconda 会自带 Jupyter Notebook,装完直接可以在开始菜单找到Jupyter Notebook图标,或者在 Anaconda Navigator 里点击 Launch。这类安装的核心优势在于 Python 环境统一由 conda 管,jupyter、ipykernel 这些依赖不太容易出幺蛾子。但劣势是,开始菜单那个图标默认启动位置写死了,很多人就是从这一步开始掉进默认路径的坑。
第二种是用 pip 单独安装。你如果已经有 Python 环境,就一行命令:
pip install jupyter notebook或者用pip install jupyterlab把下一代界面也装上。pip 装的好处是轻量、灵活、完全跟着你自己的 Python 环境走;坏处是启动命令要看环境变量配没配好,配不好就会出现"jupyter不是内部或外部命令"。
第三种是使用 Visual Studio Code 内置的 Jupyter 支持。严格意义上这不算"独立运行 Notebook",而是直接在 VS Code 里建 .ipynb 文件,选择内核就能跑。这种方式改目录的规则跟在文件资源管理器里打开文件夹的逻辑一样,你打开哪个文件夹,Notebook 就在哪个文件夹下,天然就是"指定文件夹"。
我的建议是:如果是数据科学初学者,直接 Anaconda;如果已经会配 Python 环境,pip 或者 VS Code 都行。千万别搞两套 Python 混着装,那是最容易踩到环境变量混乱的起点,后面排查起来头晕。
2.2 验证安装和环境
不管用哪种方式装完,第一步先确认你的 Jupyter 真的能正常启动。打开终端(Windows 上可以用 PowerShell、cmd,或者 Anaconda 自带的 Anaconda Prompt),输入:
jupyter --version如果正常,你会看到类似jupyter core : 5.3.0、jupyter-notebook : 7.0.6这样的版本输出。如果没有,Windows 下大概率是环境变量问题。
我强烈建议 Windows 用户优先使用 Anaconda Prompt(装 Anaconda 时自动带的),因为它的环境变量已经配好了;或者用快捷方式邮件里的"打开"这种原始方式都行。用 Anaconda Prompt 可以省掉后面一堆conda activate的麻烦。如果你在 VS Code 里装了插件,直接在终端里输入jupyter --version通常也能过,因为 VS Code 会主动加载 conda 环境。
2.3 确认当前默认工作目录
在改任何配置之前,你要先亲眼看看现在 Jupyter 默认在哪个目录启动。最直接的办法是启动一个 Notebook,然后在一个单元格里执行:
import os print(os.getcwd())再执行一个:
import notebook print(notebook.__file__)前者输出的是内核的当前工作目录,后者输出的是库文件的安装路径。你真正要关心的是前者,那才是你代码里所有相对路径的基准点。如果输出的路径不是你项目所在的位置,那你就是今天的文章的目标读者,接着往下看。
3. 五种实用方法让你在指定文件夹下启动
3.1 方法一:命令行 cd 锁定目录,最直接也最灵活
这是我最经常用的方式,因为它的思路最简单:先切目录,再启动。打开终端,然后:
cd /你的目标路径/项目文件夹 jupyter notebook在 Windows 的 PowerShell 或 cmd 里,路径换盘符的时候还要这样切换:
D: cd D:\projects\my_notebooks jupyter notebook如果你用的是 Anaconda Prompt,逻辑一模一样。启动之后,注意看终端输出的最后几行,会有一句类似Serving Notebooks from local directory: D:\projects\my_notebooks的话。如果你看到的是这个路径,说明你已经成功了,浏览器打开的 Jupyter 文件树里显示的就是这个文件夹的内容。
有一点需要提醒:很多人在cd这一步没问题,但是会因为路径里带有空格而翻车。比如cd D:\My Projects\Data Science,在命令行里这样写大概率会有问题,你需要用引号包起来:
cd "D:\My Projects\Data Science"或者干脆老老实实不要把项目路径起名带空格。这是 Windows 用户特别容易踩的一个小坑。
命令行方式的优点是完全不依赖图形界面,改任何环境变量、装任何包、切任何 conda 环境之前之后都能用;缺点是每次都要敲命令,没快捷方式那么舒服。
3.2 方法二:通过 Anaconda Navigator 图形化切换
如果你是那种"能用鼠标点就不敲代码"的人,Anaconda Navigator 是一条友好到极致的路。打开 Navigator 之后,正常情况下你会在首页看到 Notebook 的启动卡片。但很多人不知道,启动卡片的齿轮图标(设置)里藏着关键功能。
点击右上角那个齿轮,或者右键卡片选择 Open Terminal,会发现 Navigator 其实可以让你做更细的设置。但坦白讲,Navigator 能设置的是环境变量层面的内容,真正改变根目录更可靠的还是在 Navigator 里点击"Open with Jupyter Notebook"之前,你先用 Navigator 菜单里的 CMD.exe Prompt 打开一个终端,cd 到你想要的目录,再敲jupyter notebook。这种方法本质上还是方法一的图形化包装,但它解决了不想打开裸终端的小需求。
另外还有一个更实用的方案:直接打开 Navigator 里左侧的"文件浏览器"(如果有的话),定位到你的项目文件夹,然后在这个目录的地址栏里选择"在终端打开",再启动 Jupyter。拿 Navigator 当文件管理器用,反而比专门记命令行路径舒服。
3.3 方法三:修改默认配置文件,一劳永逸
如果你日复一日都是在同一个目录里干活,每次启动都要 cd 一下挺烦的。那就是时候写死配置了。
第一步,生成配置文件。在终端里执行:
jupyter notebook --generate-config这条命令会生成一个叫jupyter_notebook_config.py的文件,位置一般在用户主目录下的.jupyter文件夹里。Windows 上完整路径通常是C:\Users\你的用户名\.jupyter\jupyter_notebook_config.py;macOS/Linux 是~/.jupyter/jupyter_notebook_config.py。用任何文本编辑器打开它。
第二步,找到下面这一行(通常在文件靠前面的位置):
# c.NotebookApp.notebook_dir = ''注意这里默认是注释状态,前面有#。你要把它改成:
c.NotebookApp.notebook_dir = 'D:/projects/my_notebooks'有几点必须严格注意。第一,一定要把#去掉,注释掉的配置不会生效。第二,值一定要是普通字符串,字面意义上的文件夹路径,不要带奇怪的引号嵌套。第三,Windows 下路径里的反斜杠要小心。如果你写成'D:\projects\my_notebooks',Python 会把\p、\m这些当成转义字符,轻则路径报错,重则直接启动失败。保险做法是全部用正斜杠D:/projects/my_notebooks,或者写成双反斜杠D:\\projects\\my_notebooks,再或者前面加r变成原生字符串r'D:\projects\my_notebooks'。我强烈推荐直接用正斜杠,最不容易出错。
第三步,保存文件,重新启动 Jupyter。此时无论在哪个目录输入jupyter notebook,启动后的根目录都会是刚才写死的那一个,验证一下终端输出的Serving Notebooks from local directory是不是你的目标路径。如果还是没生效,大概率是下面的原因,看第 5 章的排查表。
3.4 方法四:定制快捷方式 / 批处理,双击就能用
这是 Windows 用户非常喜欢的一种方案,可以给每个项目做一个"专用启动图标",双击直接打开指定路径下的 Jupyter。
先说批处理文件,这是最朴素的做法。在你的项目文件夹下新建一个文本文件,把扩展名改成.bat,编辑写入:
@echo off cd /d D:\projects\my_notebooks jupyter notebook pause保存后双击这个 .bat 文件,就会先切到你的项目目录,再启动 Jupyter。窗口会一直开着,显示 Jupyter 的日志,如果出错也能立即看到。这里的cd /d是 Windows 下切换盘符路径的固定写法,很多人在cd D:\projects之后发现盘符根本没切过去,就是因为缺少/d。
再说定制快捷方式。这种方式比批处理更优雅。找到你的 Jupyter Notebook 启动入口——可能是开始菜单里的图标,也可能是 Anaconda 目录下的 jupyter-notebook.exe,右键选择"打开文件所在的位置",然后把它的快捷方式复制一份到桌面上,右键快捷方式 → 属性。
在"目标"一栏里,把原来的命令后面直接追加你的路径,等价于给 Jupyter 传了一个目录参数。比如原来目标是:
"C:\ProgramData\anaconda3\python.exe" "C:\ProgramData\anaconda3\Scripts\jupyter-notebook-script.py"可以改成:
"C:\ProgramData\anaconda3\python.exe" "C:\ProgramData\anaconda3\Scripts\jupyter-notebook-script.py" D:\projects\my_notebooks或者更简单的方式是去修改"起始位置"这一栏,填上D:\projects\my_notebooks。原理跟命令行cd一致——Jupyter 子进程会继承这个工作目录。两种改法二选一就行,我更喜欢改"起始位置",因为改动最小、不容易把原命令写坏。改了之后双击快捷方式,看看浏览器打开的文件树,确认目录没错。
3.5 方法五:JupyterLab 上传与目录切换
JupyterLab 是 Notebook 的下一代界面,很多人已经把它当主力了。它跟老版 Jupyter Notebook 的核心区别在于,Lab 本身是一个多标签工作台,可以同时开终端、开文本编辑器、开 Notebook,并且它的左侧面板有文件浏览器。但注意:这个文件浏览器跟内核的工作目录仍然是两回事。你在左侧点击进入一个项目目录,并不代表你新建的 Notebook 就保存在那里——内核的工作目录依然由启动参数决定。
JupyterLab 指定目录启动的命令是:
jupyter lab --notebook-dir=D:/projects/my_notebooks等价地,老版 Jupyter Notebook 的命令也能带这个参数:
jupyter notebook --notebook-dir=D:/projects/my_notebooks如果你已经打开了 JupyterLab,发现文件树不在目标目录,也可以直接在左侧文件浏览器里向上级目录翻,或者使用菜单File→Open from Path输入完整路径直达。这个功能对临时切换目录非常有用,但它不会改变内核的工作目录,而你代码里的相对路径依赖的是内核的工作目录。这是不少人困在"我已经点进去了为什么还是找不到 data.csv"的核心原因。
4. 实操过程与核心环节实现
4.1 典型完整流程:从零到锁定目录
要不然我直接把一个完整场景走一遍,你跟着做一遍就什么都清楚了。假设你的电脑是 Windows,安装了 Anaconda,项目文件夹在D:\work\python_models。
第一步,打开 Anaconda Prompt。第二步,输入:
D: cd D:\work\python_models jupyter notebook这时终端会刷出一行日志,其中一句类似[I ...] Serving Notebooks from local directory: D:\work\python_models,浏览器自动打开,左侧文件树显示的就是python_models里的内容。第三步,新建一个 ipynb,在第一个单元格里执行import os; print(os.getcwd()),输出应该是D:\work\python_models。到这一步,你的相对路径基准就很彻底地锁定在这里了,后续pd.read_csv('data.csv')之类都会从这个目录出发去找。
如果你照着这 3 步做完,发现浏览器里文件树显示的仍然是默认主目录或者别的什么,请直接看第 5 章的排查表,千万别反复重装。
4.2 配置文件的修改细节:逐字逐句避坑
配置文件是提升幸福感的关键一步,但恰恰也是踩坑重灾区。我把所有能踩的点一次性拿出来说清楚。
第一,配置文件的位置要确认对。终端里执行:
jupyter --config-dirWindows 下通常输出C:\Users\你的用户名\.jupyter,macOS/Linux 输出~/.jupyter。还有一个更保险的方式:
jupyter --paths这个命令会列出一堆路径,包含config、data、runtime三类路径。配置文件的生效优先级是"越靠前越高",如果你机器上有多个 Python 环境,每个环境可能有各自的配置目录,你改错了文件自然不生效。
第二,找到配置项以后,建议把整行改成:
c.ServerApp.root_dir = 'D:/work/python_models'注意,不同版本的 Jupyter 使用的配置项名有变化:老版本6.x用c.NotebookApp.notebook_dir;高版本7.x迁移成了c.ServerApp.root_dir。现在主力环境很多都是notebook 7+,直接改.jupyter目录下的jupyter_notebook_config.py时,两个配置项最好都设置一遍,反正没坏处。
第三,保存后重启 Jupyter 不要用旧的浏览器标签页。老标签页很可能还停留在旧会话上,你看着没变化以为没生效,其实新会话已经在目标目录启动了。正确姿势是把旧标签全部关掉,重新执行jupyter notebook,再看终端输出的Serving Notebooks from local directory有没有变。
第四,如果你装的是 JupyterLab,配置路径却不是jupyter_notebook_config.py,而是jupyter_server_config.py。它们俩在~/.jupyter/下共存。配置项的写法完全相同。如果你两个文件都存在,Jupyter 会合并读取,冲突时以更具体的配置优先。这种细节网上很少讲,但实际改起来最影响体验。
4.3 快捷方式与批处理:参数解释和操作布局
批处理和快捷方式看起来简单,但里面有几个非常容易搞错的细节。
先讲批处理文件。我的模板是:
@echo off title Jupyter - python_models cd /d D:\work\python_models call conda activate base jupyter notebook pause多出来的两行分别解释一下:title只是改一下终端窗口标题,方便同时开多个项目时区分;call conda activate base是保证jupyter命令在 conda 环境里能找到,如果你不是用 Anaconda 装的,这行删掉;pause是为了让窗口在你手动关闭 Jupyter 之后不要瞬间消失,保留日志。如果你在批处理里删了pause,可能遇到窗口一闪而过、根本看不到报错的情况,排查起来很痛苦。
再讲快捷方式。鼠标右键 Jupyter 的启动快捷方式 → 属性 → 目标,假设目标原本是:
"C:\ProgramData\anaconda3\python.exe" "C:\ProgramData\anaconda3\Scripts\jupyter-notebook-script.py"你就在最后加一个空格然后接路径,例如:
"C:\ProgramData\anaconda3\python.exe" "C:\ProgramData\anaconda3\Scripts\jupyter-notebook-script.py" D:\work\python_models如果你更倾向于改"起始位置",把C:\work这类目录填进去,注意不要带引号。两种方式本质都是给 Jupyter 传工作目录,但由于启动命令和起始位置在 Windows 快捷方式里的优先级偶尔有差异,一旦发现不生效,就把目标里的路径删掉,单独用起始位置来测,二选一,不要两个都写。
5. 常见问题与排查技巧实录
这一章没什么高深理论,全部是我实际操作中踩过或者被朋友问过的真实问题。遇到问题别急着重装,大多数情况下对号入座就能解决。
5.1 "jupyter" 不是内部或外部命令
这是 Windows 用户最常见的一个报错。核心原因只有一个:你的 Python 脚本目录没有加到系统环境变量 PATH 里。Anaconda 默认装的时候会问你要不要加 PATH,很多人顺手取消了,结果就到处'jupyter' 不是内部或外部命令。
解决办法有三个。第一,改用 Anaconda Prompt,它自带环境变量;第二,手动加 PATH,把C:\你的anaconda路径\Scripts和C:\你的anaconda路径\Library\bin加进去;第三,用python -m jupyter notebook启动,这个命令不依赖jupyter可执行文件在 PATH 里,但前提是当前 Python 环境的 site-packages 里装了 Jupyter。我最常推荐的是第三条,因为这个命令在任何终端里都能直接用,不跟环境变量较劲。
5.2 改了配置却不生效
优先级顺序是:命令行参数 > 环境变量 > 配置文件 > 默认值。这意味着,如果你的启动命令里带了--notebook-dir之类的参数,或者系统里设了JUPYTER_RUNTIME_DIR之类的环境变量,配置文件的指定会被覆盖。常见的"改了配置不生效"场景,也就这几类:
- 配置文件改错位置了,改到了无效路径。用
jupyter --config-dir确认。 - 配置文件里注释没去掉,或值里还有
#。 - 路径格式写错,比如反斜杠转义问题。
- 版本差异导致配置项名不匹配,
NotebookApp.notebook_dir与ServerApp.root_dir并存时互相干扰。 - 启动了多个 Jupyter 实例,旧实例还开着,新配置只对新实例生效。把旧的终端进程全部关掉再启动。
我给自己的排查套路就是:先jupyter --config-dir找到文件,再jupyter --paths看优先级,再在配置文件里搜一遍有没有notebook_dir或root_dir的残影,最后确认没有其他.pyc或者启动脚本传了参数。按顺序查,10 分钟绝对能定位。
5.3 路径带中文或空格,启动后各种怪问题
尽量用纯英文路径,这是我特别想强调的一条。倒不是说中文路径完全不能用,但在 Windows + Python 的组合下,中文路径在 Jupyter 里容易遇到编码问题,比如启动后网页上中文文件名乱码、内核报UnicodeDecodeError、文件树里部分文件夹不显示等。我用过一段时间中文路径的文件夹,体验真的很折磨,最后把所有项目全部迁移到纯英文路径下,世界就清净了。
如果你的项目实在没法改英文名,必须保证路径里不出现空格,且用正斜杠写配置。有个小技巧:Windows 的文件夹名可以带中文,但你在配置里写路径时,用正斜杠并且保存文件为 UTF-8 编码就不会太离谱,但这也是能少用就少用,不能当常规手段依赖。
5.4 conda 环境换了,Jupyter 还用旧内核
有人会有第二个 conda 环境,比如conda create -n tf python=3.9,在这个环境里装了 tensorflow,然后启动 Jupyter 却发现内核列表里没有新环境。这是因为 Jupyter 的内核(kernel)是独立注册的,跟当前激活环境不完全同步。
解决方法是先激活目标环境,再安装 ipykernel:
conda activate tf pip install ipykernel python -m ipykernel install --user --name tf --display-name "Python (tf)"这样 Jupyter 里就会出现名为Python (tf)的内核选项。这个操作不影响你指定文件夹运行,但在多环境协作时几乎必然遇到。注册好内核以后,你从哪个目录启动 Jupyter 都可以选tf内核跑,这就跟你项目文件放什么位置彻底解耦了。
5.5 启动后浏览器没自动打开
有人会遇到这样的情况:Jupyter 进程在后台跑着,终端输出也正常,但浏览器就是没自动弹出来。这通常跟配置项open_browser有关。如果你改配置的时候,手滑把它写成了:
c.NotebookApp.open_browser = False那 Jupyter 就不会自动打开浏览器了,这可能是你自己之前设的。改回True。如果没动过配置但依然不弹,可以先手动复制终端里输出的那一行地址,形如http://localhost:8888/tree?token=...,贴到浏览器里打开,八九成是可以正常访问的。
5.6 端口被占用,8888 被抢
当你启动 Jupyter 时终端会提示Port 8888 is already in use,或者启动后网页变成 8889。这是因为有一个旧的 Jupyter 进程还没退干净,或者另一个开发工具占用了 8888。我的做法是:
jupyter notebook --port 8890懒得想参数的话,直接指定一个冷门端口就行。如果要根治,就把旧进程杀掉。在 Windows 下可以Ctrl+C停掉终端里的 Jupyter,如果终端都关了进程还在,就去任务管理器里找python.exe或者jupyter相关进程,右键结束。在 macOS/Linux 下可以:
lsof -i :8888 kill -9 PIDlsof列出的第二列就是进程号 PID,直接kill掉。
写在最后的小经验
这些方法我都实打实跑过无数遍了,如果让我给别人推荐一个最顺手的组合,那就是:日常开发用命令行cd+jupyter notebook,给自己正在主攻的固定项目做一个专用快捷方式,文件路径永远锁在项目目录里。修改配置文件那一步,我建议等真的确定要用某个固定目录很久了再改,没必要一上来就全局改掉,否则当你临时想看别的目录里的旧项目时,又要绕回去,反而多一层不痛快。
另外提一句,Jupyter 7.x 之后,默认界面已经开始向 JupyterLab 收敛,新版配置文件里的ServerApp.root_dir属于长期兼容选项,哪怕将来升级,这个配置大概率也不会废弃。趁早把工作目录习惯养成,用好os.getcwd()验证每一步的结果,你就再也不会被"文件明明在却找不到"这种问题反复折磨了。