如何从Python模块项目结构外导入模块且不触发ModuleNotFoundError
问题根因
你遇到的报错是因为Python默认的模块搜索路径只包含运行主脚本的工作目录、Python安装目录等位置,不会自动包含被导入模块自身的所在目录。你在module_main.py中写的from level_1.foo_1 import ...属于不带包名的裸导入,只有运行脚本的工作目录刚好是module_example的时候才能找到level_1目录,换个执行位置就会失效。
通用解决方案(适配所有运行场景,不用额外安装)
步骤1:给所有包含Python代码的目录添加空的__init__.py文件
修改后的目录结构如下:
outer_dir/ outside_main.py module_example/ __init__.py # 新增空文件 module_main.py tests/ __init__.py # 新增空文件 test_1.py level_1/ __init__.py # 新增空文件 foo_1.py level_2/ __init__.py # 新增空文件 foo_2.py
这个文件是Python识别目录为合法包的标识,没有它Python不会把目录当作包处理。
步骤2:统一使用带包名的绝对导入,同时适配直接运行场景
修改module_main.py的代码:
# module_main.py import sys from pathlib import Path # 自动把包的上层目录加到搜索路径,适配直接运行当前脚本的场景 if __name__ == "__main__": sys.path.append(str(Path(__file__).parent.parent.resolve())) from module_example.level_1.foo_1 import foo_function_1 from module_example.level_1.level_2.foo_2 import foo_function_2 def main(): print(foo_function_1()) print(foo_function_2()) if __name__ == "__main__": main()
步骤3:修改test_1.py的导入逻辑
修改test_1.py的代码:
# test_1.py import sys from pathlib import Path # 同样把包的上层目录加到搜索路径 sys.path.append(str(Path(__file__).parent.parent.parent.resolve())) from module_example.module_main import main if __name__ == "__main__": main()
改完之后不管你在哪个目录执行outside_main.py、test_1.py还是直接执行module_main.py,都能正常导入运行。
开源库标准方案(正式发布用)
GitHub上的公开Python库普遍使用可安装包的方案,不需要手动加路径,操作如下:
- 在
module_example同级目录下新增pyproject.toml配置文件,示例内容:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "module_example" version = "0.1.0" packages = ["module_example"]
- 执行
pip install .命令把这个包安装到你的Python环境里,之后不管你在系统的哪个位置,都可以直接用from module_example.module_main import main导入,完全不需要关心路径问题。
内容的提问来源于stack exchange,提问作者CSStudent7782
相关产品推荐
相关产品推荐

