开头我先说个现象:很多人装了Jupyter Notebook之后,每次启动都发现文件列表停在某个固定位置,要么是自己的用户名目录,要么是C盘某个藏着很深的路径。想打开自己正在做的项目文件夹,就只能一层一层点进去,或者把文件夹整个拷来拷去。这个痛点几乎每个用Python做数据分析、写脚本、跑机器学习实验的人都会碰到。而“如何在指定文件夹下运行Jupyter Notebook”这个问题,看起来简单,网上教程也一大堆,但真正试过就知道,很多教程只说了一半——有的让你改配置,结果改完不生效;有的让你用cmd,但环境变量没配好又报“jupyter不是内部或外部命令”。这篇文章我直接把我自己验证过、在Windows和macOS上都跑通的方法完整写出来,顺便把那些最容易让人踩坑的细节都摊开讲,保证你照着操作能在指定文件夹下启动Notebook,折腾一次以后就不用再折腾了。
1. 为什么你的Jupyter总是打开“别人的目录”
1.1 核心痛点:默认路径与项目目录的错位
Jupyter Notebook本质上是一个跑在本机上的Web服务,启动时它会绑定一个根目录。你在浏览器里看到的文件列表,就是它从根目录读出来的。这个根目录的默认值,取决于你安装Jupyter的方式和系统设置。
如果你是用Anaconda装的标准环境,启动后大概率落在用户主目录下,也就是类似C:\Users\你的用户名。如果你用pip装,又恰好没有配置过,它可能直接落在你当前命令行的工作目录。问题来了:你实际的项目文件可能在D盘、在桌面某个子文件夹、在某个带空格的路径里。每次启动Jupyter,就像进了一个陌生人的家门,还得自己找路,非常别扭。
还有一个更隐蔽的问题:很多人以为“在Jupyter里上传文件”就是把文件放到自己电脑上的目标文件夹,实际上Jupyter的“Upload”按钮上传到的是它启动时的根目录。如果你在默认目录下启动,又在界面上上传数据文件,那文件会被扔到那个默认目录里,和你项目文件夹半毛钱关系都没有。这就导致一种很常见的连锁反应:代码里明明写了pd.read_csv('data.csv'),却一直报文件找不到,搞了半天发现数据根本不在当前工作目录。
1.2 为什么网上很多教程“抄了作业还是不行”
这个问题的坑不在方法本身,而在操作细节。我见过最多的情况是:教程让你改配置文件,你把notebook_dir那一行的注释去掉,填上路径,保存,重启Jupyter,结果没用。为什么?十有八九是路径格式问题。Windows下你填C:\Users\me\my_project,这个写法在Python字符串里会被当成转义字符处理,\U、\m这种开头会被解释成特殊字符,配置自然就失效了。
还有一种情况是:你改了配置文件,但Jupyter服务根本没有重启。配置文件只在启动时读一次,你在浏览器里关掉页面不算重启服务,你得把启动的那个黑窗口(终端)关掉,重新执行启动命令才算完。再或者,你启动了多个Jupyter实例,改的那个配置对应的进程端口和你浏览器打开的端口对不上,改了等于白改。
这些细节没有任何一个教程会主动提醒你,它们就是“肯定有效”和“试了没用”之间的分界线。我在下面的操作里会把每一步都拆开,包括怎么检查是否生效、怎么排查失败,尽量让你一次到位。
2. 最直接的办法:启动前先在命令行里切换目录
2.1 Windows下从项目文件夹启动的完整操作
先讲最省事、最不容易出错的办法,不需要改任何配置文件,也不依赖重装环境,原理就是:先让命令行的工作目录变成你的目标文件夹,再在这个目录下启动Jupyter。启动器会自然把当前工作目录作为根目录。
打开命令提示符(cmd),或者更好用的是Windows Terminal。手动操作的话,就是cd /d加上完整路径,注意/d不能省,因为只有cd /d才会同时切换盘符。比如目标文件夹是F:\python-projects\销售额分析,那就执行:
cd /d F:\python-projects\销售额分析 jupyter notebook执行完第二条命令,终端里会刷出一段日志,最后一行类似[I 14:32:05.123 NotebookApp] Serving notebooks from local directory: F:\python-projects\销售额分析。看到这句话,就说明根目录已经是你的目标文件夹了。浏览器会自动弹出或者你手动复制终端里的http://localhost:8888地址打开,文件列表里呈现的就是该文件夹的内容。
macOS或Linux下就更简单,打开终端,执行:
cd /Users/你的用户名/项目文件夹 jupyter notebook没有盘符切换的问题,cd直接切过去就好。用这个方式启动,你在Notebook里新建的.ipynb文件会直接保存在目标文件夹里,读取相对路径的数据文件、载入自己写的.py模块,全都不需要写一长串绝对路径,整个项目都在一个目录里闭环,代码可读性和可迁移性都高不少。
2.2 如何确认启动目录已经生效
不少人对“是否生效”这件事是凭感觉的,看了浏览器里的文件列表就以为对了。其实最靠谱的确认方式有两条。
第一,看终端启动日志里的Serving notebooks from local directory那一行,它会明确告诉你当前Jupyter绑定的根目录是什么。第二,在你打开的Notebook里新加一个代码单元格,执行:
import os print(os.getcwd())如果输出路径和你设置的文件夹一致,那基本就万无一失了。这两个验证点我都建议做一下,尤其是当你配置过多个Python环境、或者从IDE里拉起Jupyter的情况,有时终端显示的路径是真的,但浏览器里打开的页面来自另一个进程,导致你误判。
这里插一个之前遇到过的真实情况:我启动Jupyter后终端显示根目录是D:\my_project,但我从浏览器书签里打开的却是另外一个端口的旧实例,文件列表停在旧路径。排查了半天,发现是原来有个后台进程占着8888端口还没释放。所以记住,浏览器里看到的不一定是当前进程服务的,以终端日志为准,或者主动关掉多余的Jupyter进程。
2.3 一条命令启动:把“切换目录+启动”固化下来
如果你不需要频繁换目录,只是固定在同一个项目文件夹里干活,我建议把这两条命令打包成一个启动脚本,以后双击一下就行,省得每天重复敲。
在Windows上,新建一个文本文件,把扩展名改成.bat,内容写:
cd /d D:\my_project jupyter notebook pause保存后双击运行。如果弹出窗口一闪而过,那多半是jupyter命令找不到,说明你的Python环境没有加入系统PATH,先处理环境变量,或者改用下面这种更稳妥的写法(前提是你知道自己在哪个Python环境里):
cd /d D:\my_project python -m jupyter notebook pausepython -m jupyter notebook的意思是调用当前Python环境里安装的Jupyter模块,不依赖Scripts目录是否在PATH里,对装了多个Python版本的人更友好。pause是为了让窗口停住,方便你看到启动日志和报错信息,我建议每次都保留。macOS/Linux就把相同逻辑写进.sh文件,赋予执行权限后也能一键启动。
这个思路的本质,是用命令行的“当前工作目录”去影响Jupyter绑定根目录,它不修改任何全局配置,所以不会污染环境,也不会出现改了配置影响其他项目的情况。对于喜欢多项目并行、每个项目想独立目录的人来说,这个方式是最清爽的。
3. 修改配置文件,固定Jupyter的默认启动路径
3.1 生成配置文件并找到关键项
命令行切目录的方法虽好,但如果你的使用习惯是:从开始菜单或Anaconda Navigator里点击图标启动Jupyter,不想每次先开终端敲命令,那就需要修改Jupyter的配置文件,把默认根目录永久改成你指定的文件夹。
首先打开终端(Windows用cmd或PowerShell,macOS/Linux直接用终端),执行一次配置生成命令:
jupyter notebook --generate-config执行成功会打印一行类似Writing default config to: C:\Users\你的用户名\.jupyter\jupyter_notebook_config.py的提示,记住这个路径。如果你的环境有多个Python,最好确定生成配置文件的是你要用的那个Python环境,否则改了可能不生效(后面我会专门讲多环境的坑)。
然后用记事本或任意代码编辑器打开这个jupyter_notebook_config.py文件,在文件里搜索“notebook_dir”。你会找到一行:
# c.NotebookApp.notebook_dir = ''把前面的注释号#删掉,并在引号里填入你的目标文件夹路径,像这样:
c.NotebookApp.notebook_dir = 'D:/my_project'保存文件,重启Jupyter(注意是彻底退出进程后再启动),启动日志里的Serving notebooks from local directory就会变成你填的路径,浏览器打开后的文件列表也会直接指向那里。这个方法改的是全局默认,也就是说以后从任何入口启动的Jupyter都会默认进入这个目录,适合路径固定、长期做同一类项目的人。
3.2 路径书写格式里的那些坑
这一节值得单独拎出来讲,因为我在帮朋友排查问题的时候发现,十次配置失败里头,有八次是路径格式写错了。
先说Windows路径分隔符。在Python字符串里,反斜杠\是转义符,直接写D:\my_project,解析的时候\m可能会变成别的东西。所以配置文件里最安全的写法是下面几种之一:
- 用正斜杠:
'D:/my_project',Jupyter完全认识这种写法 - 用双反斜杠:
'D:\\my_project' - 用原始字符串前缀
r:r'D:\my_project'
我个人的习惯是一律用正斜杠,一是省去转义烦恼,二是和macOS/Linux路径写法统一,后面把代码和配置同步到服务器或别人电脑上时也不用改来改去。
第二个坑是路径里有空格。如果目标文件夹叫My Project,那么配置就要写'D:/My Project',两边单引号不能丢,空格直接落在引号内部即可。命令行如果遇到带空格的路径,记得用双引号包住整个路径,例如cd /d "D:\My Project",否则命令会被拆成两截,报“系统找不到指定的路径”。
第三个坑是中文路径。Jupyter对中文路径的支持现在做得不错,但我还是建议项目文件夹尽量用英文字母命名。中文路径偶尔会引发编码问题,尤其是在某些Windows终端默认编码不是UTF-8的情况下,启动日志乱码、文件列表里显示名称异常、某些库读取中文路径时失败。这些都属于“能用但偶尔抽风”的情况,省麻烦起见,把项目文件夹命名成sales_analysis、nlp_project这种风格,绝对稳。
3.3 配置保存了就是不生效?问题可能在这里
改了配置文件,重启了很多次,路径还是老样子。别急着怀疑自己是“非酋”,按下面的顺序排查,多半能找到问题。
第一,检查端口。默认情况下Jupyter用8888端口,如果你8888端口还在被一个旧进程占用,重启后的新进程会自动换到8889或其他端口。你浏览器里打开的可能是旧端口的页面,那显示的自然还是老根目录。处理办法是关掉所有Jupyter相关进程,确保端口释放后重新启动。Windows上用tasklist | findstr jupyter查看进程,用taskkill /F /PID 进程号清理;或者干脆重启电脑。
第二,检查Python环境的隔离。用Anaconda或者pyenv的话,很可能有多个环境。你在base环境下生成了配置文件,但每次从应用商店或图标启动用的却是另一个环境的Jupyter,两者配置文件路径不一样,修改的那个根本不被读取。保险的做法是,在同一个环境里同时执行“生成配置”和“启动Jupyter”,或者在启动后用jupyter --paths查看当前环境实际读取的配置路径,对着这个路径改。
第三,检查配置文件的语法。删掉注释之后,要确保c.NotebookApp.notebook_dir = '路径'这一行写在文件的顶层,没有缩进、没有多余的引号、没有全角标点。有时候用记事本编辑UTF-8文件保存后会产生BOM头,也会导致解析异常,不建议用记事本编辑配置文件。换用VS Code或Notepad++这种对编码支持好的编辑器,能规避掉不少莫名其妙的问题。
4. 平时用得上的几种启动姿势
4.1 桌面快捷方式:双击就进目标目录
命令行方式需要手动敲字,配置文件方式需要一次改到位。如果你觉得两者都还不够顺手,还有一个很实用的折中方案:创建一个快捷方式,让双击效果等同于“在目标文件夹下启动Jupyter”。
我常用的是下面这个思路,以Windows为例说明。在桌面上右键新建快捷方式,目标位置填:
cmd /k "cd /d D:\my_project && python -m jupyter notebook"快捷方式的“起始位置”也可以顺手填成D:\my_project,双保险。/k参数表示命令执行完不自动关窗口,留在那里方便你看日志,也能随时关掉服务。这个快捷方式不用改系统配置,不影响其他项目目录,而且做得明明白白:一看图标就知道是哪个项目的入口。多个项目就做多个快捷方式,互不打扰。这是目前我自己最偏爱的方案,因为它的行为是可预期的,不藏“黑魔法”。
macOS的做法类似,可以写一个AppleScript或者在Automator里新建一个“运行Shell脚本”的应用程序,内容就是cd /Users/你/项目路径 && jupyter notebook,保存后也能双击启动。
4.2 从Anaconda Navigator和VS Code里控制启动目录
如果你习惯用Anaconda Navigator的图形界面启动,可以在Navigator里先找到Jupyter Notebook下方的“Launch”按钮,注意它启动时继承的是Navigator当前的工作目录,但这个当前目录本身不太好直接控制。更干脆的办法是:在Navigator首页的“Environments”里选中你的环境,点击那个环境的“Open Terminal”按钮,先cd到目标目录,再输入jupyter notebook,这样既能确保是该环境下的Jupyter,又能确认目录是你想要的。
而如果你用VS Code写代码,就不太需要单独开Jupyter了。在VS Code里安装好Jupyter扩展后,打开项目文件夹就能直接新建ipynb,它的根目录默认就是当前打开的文件夹。这种方式完全避开“指定文件夹”的困扰,因为编辑器的工作区本身就是你的项目目录。唯一要注意的是,VS Code的Jupyter运行内核可能默认走它自己绑定的Python解释器,你需要在右下角选择正确的工作内核,这一步也同样要匹配你的项目环境。
4.3 配置JupyterLab时顺带把目录设好
JupyterLab是Notebook的“下一代界面”,和Notebook共享启动进程,所以它在指定目录上的逻辑和Notebook完全一致。你如果配置好了notebook_dir,那启动jupyter lab默认也是进这个目录。我补充这一点,是因为现在很多新手装上Jupyter之后,实际打开的地址是/lab而不是/tree,如果你在网上搜的是老教程,给出的配置文件路径设置可能对JupyterLab不起作用,但现代版本里两者是共用的配置,改notebook_dir两边都能生效。
如果你同时用Notebook和Lab,建议每天固定用一种界面,避免在两种UI下反复切换产生认知负担。启动命令区分得很清楚:jupyter notebook进传统界面,jupyter lab进Lab。同一个目录,只是入口不同。
5. 实操中容易卡住的几个问题与排查思路
5.1 提示“jupyter不是内部或外部命令”
这个报错在Windows上最常见,本质上就是系统找不到jupyter命令。原因很简单:Python的Scripts目录没有加到PATH环境变量里。不推荐偷懒去手动改PATH,虽然能解决,但改不好容易影响系统。我推荐直接换成python -m jupyter notebook或者python3 -m jupyter notebook,这样不管Jupyter装在哪里,只要Python在环境变量里能找到,就能通过模块的方式启动它。用过Python虚拟环境的人应该深有体会,python -m pip、python -m jupyter这套写法就是用来绕开可执行文件路径问题的,一劳永逸。
如果你用的是Anaconda,遇到这个报错大概率是Anaconda的Scripts目录也不在PATH里,或者你启动的是系统自带的Python而不是conda环境里的Python。可以先在终端执行where python(Windows)或which python(macOS/Linux),看看当前默认的Python是哪一个环境里的,再决定用conda activate切换环境。
5.2 用Python模块启动后浏览器不自动打开也没关系
有时候你用python -m jupyter notebook在服务器或者远程环境里启动,它会提示你访问带token的地址,但不会自动弹浏览器。这不算一个问题,反而是一个安全机制。你只需要手动复制粘贴那行地址到浏览器就能访问。这也提示一个值得养成的习惯:启动日志里的token是有有效期而且和当前会话绑定的,如果你浏览器清缓存或者过了一段时间访问提示需要密码,回到终端刷新页面或者重启Jupyter进程即可,不要去网上找别人分享的神秘token。
5.3 端口被占用和旧进程残留的清理方法
我在前面提到过端口冲突导致根目录看起来没变的情况,这里具体说下处理方法。如果你启动的时候终端报错Address already in use,说明8888端口被别的进程占用了。要么给启动命令换一个端口,例如jupyter notebook --port=8899,要么干脆把占用端口的旧进程清掉。
在Windows上,可以用:
netstat -ano | findstr :8888找到占用端口的PID,再用taskkill /F /PID 那个数字结束进程。macOS上用lsof -i :8888查看PID,kill -9 那个数字结束进程。至于这个占用进程是不是旧Jupyter,你也可以在任务管理器里确认下再动手。
我建议如果长时间用一台电脑做数据分析,隔一段时间清理一次残留的Python进程,能减少很多“改配置不生效”“文件莫名消失”这类诡异问题。这些进程有时候是保存失败或者异常退出遗留下来的,不清理就会导致新实例启动到别的端口,而你浏览器里还停在老页面上。
5.4 常见问题速查表
| 症状 | 可能原因 | 排查/解决方法 |
|---|---|---|
| 浏览器文件列表和终端显示的路径不一致 | 浏览器打开的是旧端口实例 | 彻底关闭所有Jupyter进程,重新启动 |
| 修改配置文件后不生效 | 改错了环境、路径格式不对、没重启进程 | 用jupyter --paths核对配置路径,确认当前Python环境,检查正斜杠/反斜杠 |
jupyter找不到命令 | Scripts目录不在PATH | 改用python -m jupyter notebook,或在Anaconda里先conda activate |
| 启动时报端口占用 | 8888被旧进程占用 | 换端口--port=8899,或用netstat/lsof找到PID后清理 |
| 想用固定文件夹但不想改命令行 | 没有固化启动方式 | 创建快捷方式或bat/sh脚本,固定cd /d 路径 && jupyter notebook |
代码里os.getcwd()跟预期不一致 | 根目录是默认目录而不是项目目录 | 按本文第2章启动方式操作,并用os.getcwd()验证 |
5.5 我整理的一些经验要点
最后补充几条实操心得,这些不算步骤,更像是打磨出来的习惯:
第一,项目文件夹路径里面不要放空格和中文虽然不是说一定会出问题,但NLP、爬虫、机器学习这类项目经常要用到第三方库,第三方库对路径的解析水平参差不齐,与其事后排查,不如事先避免。
第二,python -m永远是排查问题的“万能钥匙”。无论你用的是哪个环境、哪个脚本,python -m 工具名这种方式都能绕开可执行文件路径的混乱,我排查Jupyter问题时第一个习惯就是看python -m jupyter notebook能不能正常起,如果正常,那问题多半出在环境变量或路径配置上。
第三,启动日志要认真留着。很多人一看到那一堆INFO日志就觉得没用,实际上报错信息、端口号、配置文件加载路径全在里面。你遇到问题时,把这段日志截图发出去,比反复描述“弹了个框那个框闪一下没了”有效得多。
第四,Jupyter的根目录和Notebook里代码执行的工作目录默认是一致的,但如果你用VS Code或者某些远程插件启动,二者可能会脱节。建议每次开始干活前跑一遍os.getcwd(),几十秒的时间,能避免你半天以后才发现数据路径全是错的。这个小检查已经成为我每天写代码之前的固定动作了。
写在最后的小建议
每次启动Jupyter都迷失在陌生目录里,这个事儿其实不是技术门槛高,而是它涉及的知识点太杂碎:环境变量、路径转义、配置文件、进程端口,哪个环节掉链子都会让你觉得某个方法不灵。我自己刚接触那会儿也在“配置不生效”“端口被占”这些地方反复折腾过,后来形成的做法是:能不改全局尽量不改,优先用“切换目录再启动”或者快捷方式;必须改配置时,只改notebook_dir,不改其他参数;出现诡异问题,先把所有Python进程清干净。这套思路到目前为止在Windows、macOS和远程Linux服务器上都验证过,基本没有失手的时候。你把这几个方法都过一遍之后,以后无论是写爬虫、做数据分析、跑深度学习实验,都能主动掌控自己的工作目录了。