Python如何从根目录导入模块?报错求更优解决方案
解决Python跨目录模块导入的ModuleNotFoundError问题
首先先明确你的目录结构,方便理解问题:
myapp/ ├── definitions.py └── src/ └── scripts/ └── start.py
你遇到的报错原因很简单:Python默认只会在当前脚本所在目录和系统环境变量PYTHONPATH包含的路径里查找可导入的模块。start.py在myapp/src/scripts/下,而definitions.py在它的两级上级目录,不在Python默认的搜索路径里,所以会找不到。
你用sys.path.insert(1, '../../')的方法确实能解决问题,但这个方案有个小缺点:如果以后你改变了脚本的运行位置或者目录结构,相对路径可能会失效,不够健壮。下面给你几个更优的方案:
方案1:把myapp变成可导入的Python包
这是最推荐的Python项目规范做法:
- 在
myapp/和myapp/src/目录下都创建一个空的__init__.py文件(用来标记这是Python包目录),目录结构变成:myapp/ ├── __init__.py ├── definitions.py └── src/ ├── __init__.py └── scripts/ └── start.py - 之后你可以用两种方式导入:
- 绝对导入(推荐,更清晰):
修改start.py的导入代码为:
运行的时候需要确保from myapp import definitions if __name__ == '__main__': print('in start = ' + definitions.ROOT_DIR)myapp所在的父目录在PYTHONPATH里,或者直接在myapp的父目录下运行:python -m myapp.src.scripts.start - 相对导入(仅在包内部运行时可用):
修改start.py为:
注意这种方式不能直接用from ... import definitions if __name__ == '__main__': print('in start = ' + definitions.ROOT_DIR)python start.py运行,必须用模块方式启动(就是上面的python -m ...命令)。
- 绝对导入(推荐,更清晰):
方案2:设置PYTHONPATH环境变量
如果你不想修改目录结构,可以通过环境变量告诉Python去哪里找模块:
- Linux/macOS终端:运行
start.py前先执行:
然后直接运行export PYTHONPATH="/绝对路径/to/myapp:$PYTHONPATH"python start.py就能正常导入了。 - Windows命令行:
之后再运行脚本即可。set PYTHONPATH=C:\绝对路径\to\myapp;%PYTHONPATH%
如果你想永久生效,可以把这个命令加到你的shell配置文件(比如Linux的~/.bashrc,macOS的~/.zshrc)或者Windows的系统环境变量里。
方案3:用setuptools做项目打包(适合中大型项目)
如果你的项目以后会不断扩展,建议用Python的打包工具来管理:
- 在
myapp目录下创建pyproject.toml文件,内容示例:[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "myapp" version = "0.1.0" packages = ["myapp", "myapp.src"] - 然后在
myapp的父目录下,用开发模式安装这个包:
这样之后,你在任何地方都可以直接用pip install -e .from myapp import definitions来导入,完全不用担心路径问题。
对比下来,方案1是最符合Python项目规范的,方案2适合快速临时解决,方案3适合长期维护的项目。
内容的提问来源于stack exchange,提问作者topcan5
相关产品推荐
相关产品推荐

