Python子目录脚本导入父目录包报ModuleNotFoundError
问题原因
你碰到的ModuleNotFoundError: No module named 'subdir'由三个常见的Python导入误区共同导致:
sys.path.append("..")添加的是相对当前终端工作目录的路径,不是相对test2.py文件所在位置的路径。如果你直接在subdir2目录下启动脚本、或是VS Code默认工作目录不是项目根目录,这个..指向的路径根本不是项目根目录,Python自然找不到subdir包。- 你的
subdir/__init__.py存在笔误:文件里写的导入目标是subdir.test_class1、subdir.test_class2,但实际目录下的文件名是class1.py、class2.py,文件名不匹配本身就会触发导入错误。 __init__.py里硬写from subdir.xxx import xxx的绝对导入写法,要求运行时项目根目录必须在Python的模块搜索路径列表里,否则识别不到subdir这个顶级包名。
解决方案
下面两种方案都可以解决问题,按需选择即可。
方案1:动态添加项目根目录到搜索路径(适配本地直接运行脚本的场景)
这个方案不依赖启动脚本时的工作目录,无论你从哪个路径启动test2.py都能正常运行,不需要调整VS Code配置或者启动命令。
- 先修正
subdir/__init__.py的导入逻辑,顺便修复笔误,包内优先用相对导入兼容性更好:
# 原错误写法:from subdir.test_class1 import Apple(文件名错误+硬编码顶级包名) from .class1 import Apple from .class2 import Banana
- 修改
subdir/subdir2/test2.py的路径添加逻辑,基于当前文件的绝对路径动态计算项目根目录,避免相对路径的不确定性:
import sys import os # 先获取当前test2.py的绝对所在目录,向上回溯两级就是项目根目录init_file_testing current_file_path = os.path.abspath(__file__) current_dir = os.path.dirname(current_file_path) project_root = os.path.dirname(os.path.dirname(current_dir)) # 把项目根目录插入到搜索路径最前面,避免同名包干扰 sys.path.insert(0, project_root) from subdir import Apple from subdir import Banana a = Apple("red") print(a) b = Banana("yellow") print(b)
修改完成后直接运行test2.py即可正常执行。
方案2:以模块模式启动脚本(符合Python包规范的标准方案)
Python官方推荐的包内脚本运行方式,不需要手动修改sys.path,只要从项目根目录以模块参数启动即可:
- 按照方案1的步骤先修正
subdir/__init__.py的笔误和导入写法。 - 打开终端,切换到项目根目录
init_file_testing下,执行以下命令启动脚本:
python -m subdir.subdir2.test2
这种启动方式会自动把当前终端所在的项目根目录加入模块搜索路径,导入逻辑和根目录下test1.py的运行逻辑完全一致,不会出现找不到包的问题。如果要在VS Code里点击运行按钮直接启动,可以修改launch.json配置,把cwd字段设为项目根目录,同时给启动参数加上-m subdir.subdir2.test2即可。
避坑提示
- 永远不要在代码里写
sys.path.append("..")这类硬编码的相对路径,只要启动脚本时的工作目录变化,路径就会指向错误位置,问题排查成本极高。 - 包内部的模块互相导入时,优先使用
.开头的相对导入,不要硬编码顶级包名,后续如果要把整个包迁移到其他项目,导入逻辑不需要修改就能正常运行。 - 导入时填写的模块名必须和实际文件名完全一致,大小写、后缀前的名称都不能错,否则就算路径正确也会触发导入错误。
内容的提问来源于stack exchange,提问作者KishuInu
相关产品推荐
相关产品推荐

