VS Code 中 Python 相对路径失效?从 `FileNotFoundError` 深入理解当前工作目录问题
目录VS Code 中 Python 相对路径失效从 FileNotFoundError 深入理解当前工作目录问题1. 问题背景2. 问题的本质相对路径不是相对于 py 文件而是相对于“当前工作目录”3. 为什么 PyCharm 里经常没问题而 VS Code 容易出问题4. 第一种解决方案让 VS Code 普通运行时从当前文件目录启动5. 第二种解决方案Debug 时配置 launch.json6. 有了 launch.json 仍然不生效通常是这几个原因6.1 launch.json 放错位置6.2 Debug 时没有选中对应配置6.3 点击的是右上角 Debug 按钮7. 最推荐的工程写法不要依赖 VS Code 的当前工作目录8. 为什么 Path(__file__).resolve().parents[2] 是项目根目录9. 建议封装一个通用路径工具10. 另一个实用技巧自动读取最新生成的文件11. 排查路径问题的固定模板12. 最终推荐方案13. 总结VS Code 中 Python 相对路径失效从FileNotFoundError深入理解当前工作目录问题1. 问题背景在 Python 数据分析项目中我们经常会把代码文件和数据文件分开放置例如sample_turbine_mast_analysis ├─ output │ └─ all_files_resampled_20260611_162930.csv │ └─ veer_power_analysis └─ 01_preprocessing └─ m1_nacelle_wind_bias.py当前运行的 Python 文件是sample_turbine_mast_analysis/veer_power_analysis/01_preprocessing/m1_nacelle_wind_bias.py想读取的 CSV 文件是sample_turbine_mast_analysis/output/all_files_resampled_20260611_162930.csv于是很自然地写出下面代码importpandasaspd dfpd.read_csv(../../output/all_files_resampled_20260611_162930.csv)从目录结构上看这个路径似乎没问题当前 py 文件目录 sample_turbine_mast_analysis/veer_power_analysis/01_preprocessing ../../output/ 等价于 sample_turbine_mast_analysis/output/但运行时却报错FileNotFoundError: [Errno 2] No such file or directory: ../../output/all_files_resampled_20260611_162930.csv这类问题在 PyCharm 中可能很少遇到但在 VS Code 中非常常见。2. 问题的本质相对路径不是相对于 py 文件而是相对于“当前工作目录”很多初学者都会有一个误解Python 中的相对路径是相对于当前正在运行的.py文件所在目录。但真实情况通常是Python 中的相对路径是相对于当前工作目录也就是os.getcwd()或Path.cwd()所指向的位置。也就是说代码中写的../../output/all_files_resampled_20260611_162930.csv并不一定是从m1_nacelle_wind_bias.py所在目录开始往上找而是从当前工作目录开始往上找。可以用下面代码验证frompathlibimportPathimportsysprint(当前运行的 Python 路径)print(sys.executable)print(当前工作目录)print(Path.cwd())print(当前 py 文件所在目录)print(Path(__file__).resolve().parent)实际输出为当前运行的 Python 路径 C:\Users\54867\.conda\envs\ewm_ti\python.exe 当前工作目录 F:\09-code\20-LTC这就说明VS Code 当前运行时的起点并不是F:\09-code\20-LTC\sample_turbine_mast_analysis\veer_power_analysis\01_preprocessing而是F:\09-code\20-LTC因此这行代码pd.read_csv(../../output/all_files_resampled_20260611_162930.csv)实际会被解释成F:\09-code\20-LTC\..\..\output\all_files_resampled_20260611_162930.csv也就是F:\output\all_files_resampled_20260611_162930.csv但真实文件在F:\09-code\20-LTC\sample_turbine_mast_analysis\output\all_files_resampled_20260611_162930.csv所以必然报错。3. 为什么 PyCharm 里经常没问题而 VS Code 容易出问题因为二者默认的运行习惯不同。PyCharm 通常会比较明确地设置运行配置比如当前脚本路径当前工作目录Python 解释器环境变量参数配置。很多情况下PyCharm 的运行目录会更接近当前脚本所在目录或者至少能在 Run Configuration 里直观看到。而 VS Code 更灵活但也更容易“隐式”出问题。它可能把下面这个目录作为当前工作目录F:\09-code\20-LTC也就是 VS Code 当前打开的工作区根目录。这就会导致一个现象同一段相对路径代码在 PyCharm 能跑在 VS Code 报FileNotFoundError。本质不是 pandas 的问题也不是文件不存在而是路径解析起点变了。4. 第一种解决方案让 VS Code 普通运行时从当前文件目录启动如果只是点击 VS Code 右上角的普通运行按钮例如Run Python File可以设置{python.terminal.executeInFileDir:true}设置方法打开 VS Code按Ctrl Shift P输入Preferences: Open User Settings (JSON)加入{python.terminal.executeInFileDir:true}这个配置的作用是普通运行 Python 文件时把当前工作目录切换为当前.py文件所在目录。设置之后运行frompathlibimportPathprint(Path.cwd())期望输出应该变成F:\09-code\20-LTC\sample_turbine_mast_analysis\veer_power_analysis\01_preprocessing这样pd.read_csv(../../output/all_files_resampled_20260611_162930.csv)就可以正常找到文件。但是要注意这个配置主要影响普通运行不一定影响 Debug。5. 第二种解决方案Debug 时配置launch.json如果使用的是 Debug例如F5或者左侧“运行和调试”那么 VS Code 通常会读取项目下的.vscode/launch.json这时需要显式设置cwd。推荐配置如下{version:0.2.0,configurations:[{name:Python Debug 当前文件目录,type:debugpy,request:launch,program:${file},console:integratedTerminal,cwd:${fileDirname},justMyCode:true}]}其中最关键的是cwd:${fileDirname}意思是Debug 时把当前工作目录设置为当前正在运行的.py文件所在目录。如果 VS Code 当前打开的工作区是F:\09-code\20-LTC那么launch.json应该放在F:\09-code\20-LTC\.vscode\launch.json而不是放在F:\09-code\20-LTC\sample_turbine_mast_analysis\.vscode\launch.json也不是放在更深层目录。这是一个非常容易踩坑的点。6. 有了 launch.json 仍然不生效通常是这几个原因6.1 launch.json 放错位置假设 VS Code 打开的根目录是F:\09-code\20-LTC那么 VS Code 会优先读取F:\09-code\20-LTC\.vscode\launch.json如果你把配置文件放到了F:\09-code\20-LTC\sample_turbine_mast_analysis\.vscode\launch.json但 VS Code 打开的根目录不是sample_turbine_mast_analysis那这个配置可能不会被使用。6.2 Debug 时没有选中对应配置创建了launch.json后左侧“运行和调试”顶部会出现一个配置下拉框。需要选择Python Debug 当前文件目录然后再按 F5。如果仍然使用默认的Python Debugger: Current File那可能不会走你自定义的cwd配置。6.3 点击的是右上角 Debug 按钮VS Code 右上角的 Debug 按钮有时不走左侧选中的 Debug 配置。如果想让右上角的 Debug 按钮也使用这个配置可以尝试增加purpose:[debug-in-terminal]完整示例{version:0.2.0,configurations:[{name:Python Debug 当前文件目录,type:debugpy,request:launch,program:${file},console:integratedTerminal,cwd:${fileDirname},purpose:[debug-in-terminal],justMyCode:true}]}不过更稳妥的做法是从左侧“运行和调试”中选择自己的配置然后启动 Debug。7. 最推荐的工程写法不要依赖 VS Code 的当前工作目录虽然可以通过 VS Code 设置解决问题但从工程稳定性来说更推荐直接在代码中基于当前.py文件定位路径。也就是不要写pd.read_csv(../../output/all_files_resampled_20260611_162930.csv)而是写frompathlibimportPathimportpandasaspd# 当前 py 文件# sample_turbine_mast_analysis/veer_power_analysis/01_preprocessing/m1_nacelle_wind_bias.pycurrent_filePath(__file__).resolve()# 项目根目录# sample_turbine_mast_analysisproject_rootcurrent_file.parents[2]# 目标 CSV 文件csv_pathproject_root/output/all_files_resampled_20260611_162930.csvprint(当前 py 文件,current_file)print(项目根目录,project_root)print(CSV 路径,csv_path)print(文件是否存在,csv_path.exists())dfpd.read_csv(csv_path,encodingutf-8-sig)这段代码不关心 VS Code 当前工作目录是什么。无论你在VS Code 普通运行VS Code DebugPyCharm命令行定时任务其他 IDE只要这个.py文件和output文件夹的相对位置不变它就能稳定找到数据文件。8. 为什么Path(__file__).resolve().parents[2]是项目根目录当前文件路径是F:\09-code\20-LTC\sample_turbine_mast_analysis\veer_power_analysis\01_preprocessing\m1_nacelle_wind_bias.py那么Path(__file__).resolve().parent得到F:\09-code\20-LTC\sample_turbine_mast_analysis\veer_power_analysis\01_preprocessing继续往上Path(__file__).resolve().parents[0]得到F:\09-code\20-LTC\sample_turbine_mast_analysis\veer_power_analysis\01_preprocessingPath(__file__).resolve().parents[1]得到F:\09-code\20-LTC\sample_turbine_mast_analysis\veer_power_analysisPath(__file__).resolve().parents[2]得到F:\09-code\20-LTC\sample_turbine_mast_analysis而output文件夹正好在F:\09-code\20-LTC\sample_turbine_mast_analysis\output所以可以拼接csv_pathproject_root/output/all_files_resampled_20260611_162930.csv最终得到F:\09-code\20-LTC\sample_turbine_mast_analysis\output\all_files_resampled_20260611_162930.csv9. 建议封装一个通用路径工具如果项目中很多脚本都需要读取output、input、data等目录可以封装一个简单函数。例如在项目中创建sample_turbine_mast_analysis └─ utils └─ paths.py内容如下frompathlibimportPathdefget_project_root()-Path: 获取项目根目录sample_turbine_mast_analysis 当前文件位于 sample_turbine_mast_analysis/utils/paths.py 所以 parent.parent 即为项目根目录。 returnPath(__file__).resolve().parent.parentdefget_output_dir()-Path: 获取 output 目录。 returnget_project_root()/outputdefget_output_file(filename:str)-Path: 获取 output 目录下的某个文件路径。 returnget_output_dir()/filename然后在业务脚本中这样使用importpandasaspdfromutils.pathsimportget_output_file csv_pathget_output_file(all_files_resampled_20260611_162930.csv)print(CSV路径,csv_path)print(文件是否存在,csv_path.exists())dfpd.read_csv(csv_path,encodingutf-8-sig)这种写法的好处是路径逻辑集中管理每个脚本不用重复写parents[2]后续项目目录变化时只需要改一个地方更适合多人协作和长期维护。10. 另一个实用技巧自动读取最新生成的文件有些输出文件带有时间戳例如all_files_resampled_20260611_162930.csv这种文件名容易变如果代码写死文件名下一次重新生成文件后就可能找不到。可以改成自动读取最新文件frompathlibimportPathimportpandasaspd project_rootPath(__file__).resolve().parents[2]output_dirproject_root/outputcsv_fileslist(output_dir.glob(all_files_resampled_*.csv))ifnotcsv_files:raiseFileNotFoundError(f没有找到 all_files_resampled_*.csv 文件目录{output_dir})latest_csvmax(csv_files,keylambdap:p.stat().st_mtime)print(读取最新文件,latest_csv)dfpd.read_csv(latest_csv,encodingutf-8-sig)这样不需要每次手动改时间戳文件名。11. 排查路径问题的固定模板以后遇到路径问题可以先加下面这段代码frompathlibimportPathimportsysprint(*80)print(Python解释器)print(sys.executable)print(\n当前工作目录 Path.cwd())print(Path.cwd())print(\n当前 py 文件路径)print(Path(__file__).resolve())print(\n当前 py 文件所在目录)print(Path(__file__).resolve().parent)test_pathPath(../../output/all_files_resampled_20260611_162930.csv)print(\n原始相对路径)print(test_path)print(\n解析后的绝对路径)print(test_path.resolve())print(\n文件是否存在)print(test_path.exists())print(*80)这段代码可以快速回答三个关键问题当前 Python 解释器是不是对的当前工作目录到底在哪里相对路径最终被解析到了哪里。只要把这三个问题搞清楚绝大多数FileNotFoundError都能快速定位。12. 最终推荐方案对于 VS Code可以做两层处理。第一层改善 VS Code 运行体验用户级settings.json中加入{python.terminal.executeInFileDir:true}项目级.vscode/launch.json中加入{version:0.2.0,configurations:[{name:Python Debug 当前文件目录,type:debugpy,request:launch,program:${file},console:integratedTerminal,cwd:${fileDirname},justMyCode:true}]}第二层代码中不要依赖 IDE 的当前工作目录而是使用frompathlibimportPath project_rootPath(__file__).resolve().parents[2]csv_pathproject_root/output/all_files_resampled_20260611_162930.csv这才是最稳的方式。13. 总结这次问题的核心不是文件不存在也不是 pandas 读取 CSV 的问题而是VS Code 的当前工作目录和当前 Python 文件所在目录不是一回事。相对路径../../output/xxx.csv看起来是从当前.py文件出发但实际是从Path.cwd()出发。因此只要 VS Code 当前工作目录不是你以为的位置路径就会找偏最终报FileNotFoundError解决这类问题最重要的是记住一句话写给自己临时调试的脚本可以调整 VS Code 的cwd写给项目长期使用的代码应该基于__file__构造绝对路径。这样才能避免同一段代码在 PyCharm 能跑、VS Code 不能跑、命令行又报错的问题。