运行pytest遇ModuleNotFoundError,主程序报相对导入越界错误
问题描述
项目文件结构:
.(root) ├── __init__.py ├── tests/ │ ├── __init__.py │ └── animation_tests/ │ ├── __init__.py │ └── test_other_animations.py └── src/ ├── __init__.py ├── alien_onslaught.py ├── animations/ │ ├── __init__.py │ └── other_animations.py └── utils/ ├── __init__.py └── animation_constants.py
场景1:使用绝对导入from utils.animation_constants import ...
在test_other_animations.py中导入:
from src.animations.other_animations import DestroyAnim, MissileEx, Immune
运行pytest时触发错误:
ImportError while importing test module 'C:\Users\Rux\Desktop\Programming\Projects\AlienOnslaught\alien_onslaught\tests\animation_tests\test_other_animations.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: C:\Users\Rux\AppData\Local\Programs\Python\Python311\Lib\importlib\__init__.py:126: in import_module return _bootstrap._gcd_import(name[level:], package, level) test_other_animations.py:7: in <module> from src.animations.other_animations import DestroyAnim, MissileEx, Immune > ..\..\src\animations\other_animations.py:10: in <module> from utils.animation_constants import ( E ModuleNotFoundError: No module named 'utils'
场景2:使用相对导入from ..utils.animation_constants import ...
修改other_animations.py的导入后,测试可正常运行,但启动主程序alien_onslaught.py时出错:
Traceback (most recent call last): File "C:\Users\Rux\Desktop\Programming\Projects\AlienOnslaught\Alien-Onslaught-main\src\alien_onslaught.py", line 21, in <module> from game_logic.collision_detection import CollisionManager File "C:\Users\Rux\Desktop\Programming\Projects\AlienOnslaught\Alien-Onslaught-main\src\game_logic\collision_detection.py", line 8, in <module> from entities.projectiles import Missile File "C:\Users\Rux\Desktop\Programming\Projects\AlienOnslaught\Alien-Onslaught-main\src\entities\projectiles.py", line 16, in <module> from animations.other_animations import MissileEx File "C:\Users\Rux\Desktop\Programming\Projects\AlienOnslaught\Alien-Onslaught-main\src\animations\other_animations.py", line 10, in <module> from ..utils.animation_constants import ( ImportError: attempted relative import beyond top-level package
核心矛盾:测试和主程序的导入逻辑无法兼容,绝对/相对导入均不能同时满足两种场景。
解决方案
方法1:统一用src开头的绝对导入,确保项目根目录在Python路径中
- 修改
other_animations.py的导入语句:
from src.utils.animation_constants import ( destroy_frames, missile_ex_frames, alien_immune_frames, )
- 运行测试:
- 直接在项目根目录执行
pytest命令; - 或者先把根目录加入PYTHONPATH:
Windows:set PYTHONPATH=C:\Users\Rux\Desktop\Programming\Projects\AlienOnslaught\alien_onslaught
Linux/macOS:export PYTHONPATH=/path/to/your/project/root
再执行pytest。
- 直接在项目根目录执行
- 启动主程序:从项目根目录运行
python src/alien_onslaught.py。
方法2:配置pytest自动识别根目录
在项目根目录创建pytest.ini文件,内容如下:
[pytest] pythonpath = .
这样pytest会自动把根目录加入Python路径,此时用src开头的绝对导入,测试和主程序(从根目录启动)都能正常运行。
方法3:给主程序添加路径适配逻辑
修改alien_onslaught.py的入口部分:
if __name__ == "__main__": import sys from pathlib import Path # 把项目根目录添加到Python路径 project_root = Path(__file__).parent.parent sys.path.append(str(project_root)) # 后续导入和主程序逻辑 from game_logic.collision_detection import CollisionManager # ...其他代码
配合src开头的绝对导入,无论从哪个路径启动主程序,都能正确找到模块,测试也能正常运行。
方法4:用模块方式启动主程序
保持other_animations.py的相对导入不变,从项目根目录用-m参数启动主程序:
python -m src.alien_onslaught
这种方式下Python会把根目录视为包的父目录,相对导入不会报错,测试也能正常运行(因为测试从根目录导入src模块,包内相对导入有效)。
内容的提问来源于stack exchange,提问作者Khada Ake
相关产品推荐
相关产品推荐

