Python项目tests目录导入app包模块报错问题咨询
报错根本原因
你遇到的ModuleNotFoundError: No module named 'app'错误是因为Python运行脚本时的模块搜索路径(sys.path)默认不包含你的项目根目录E:\project,直接执行tests/test.py时,Python只会从test.py所在的tests目录、Python安装目录、系统内置库路径等位置搜索模块,找不到上层的app包。
你使用的python -m tests.test是完全符合Python规范的合法用法,不属于临时方案:-m参数会把当前执行命令的工作目录自动加入sys.path,同时把test.py作为tests包的子模块运行,能完美解决路径问题。
更合理的长期方案
1. 先补全包结构标记
在app目录、tests目录下各添加一个空的__init__.py文件,标记这两个目录为Python可识别的包,结构如下:
E:\project ├── app │ ├── __init__.py │ └── hello │ ├── __init__.py │ └── hello.py └── tests ├── __init__.py └── test.py
2. 针对日常调试的轻量方案
方案A:配置PYTHONPATH环境变量
把项目根目录E:\project添加到系统的PYTHONPATH环境变量中,配置完成后重启终端,所有Python脚本都能全局识别app包,无需额外配置。
方案B:脚本内临时注入搜索路径
在test.py文件最开头加入以下代码,手动把项目根目录加入搜索路径,之后可以直接运行python test.py:
import sys from pathlib import Path # 把test.py所在目录的上层目录(项目根目录)加入搜索路径 sys.path.append(str(Path(__file__).parent.parent.resolve())) # 后续正常导入即可 from app.hello.hello import greeting
3. 针对测试场景的标准方案
如果使用pytest做单元测试(Python生态最主流的测试框架),只需在项目根目录新建pytest.ini配置文件,内容如下:
[pytest] pythonpath = .
之后直接在项目根目录执行pytest命令,框架会自动识别所有测试用例,无需手动处理路径,也不需要用-m参数指定测试文件。
4. 长期维护项目的最佳实践
如果你的项目需要长期迭代、或者要发布给他人使用,推荐在项目根目录新建pyproject.toml配置文件,填写基础的项目信息,之后在虚拟环境中执行:
pip install -e .
这个命令会把你的项目以可编辑模式安装到虚拟环境的库路径中,之后不管在哪个位置运行脚本,都能直接导入app包,是工业界的标准做法。
相对导入报错的原因说明
你尝试的相对导入在VS Code中不报错是因为IDE会自动补全项目路径做静态检查,但运行时失效是因为:相对导入只能在被作为包子模块的文件中使用,直接运行test.py时,该文件的身份是顶层脚本__main__,不属于tests包的一部分,因此相对导入规则不生效,避免直接运行带相对导入的脚本即可。
内容的提问来源于stack exchange,提问作者jhon.smith

