Python模块嵌套导入时兼容主脚本与pytest测试的解决方案
问题根源
这个导入冲突本质是Python的模块搜索路径规则导致的,两种导入写法报错的核心原因:
- 用
from strings import String的绝对导入时:在PyUtils目录下跑pytest,Python会把当前PyUtils目录加入搜索路径,能找到同目录的strings.py;但在上层scripts目录跑主脚本时,Python的搜索路径是scripts目录,找不到嵌套在PyUtils里的strings模块,直接报模块不存在。 - 改成
from .strings import String的相对导入时:上层主脚本导入PyUtils包时,Python能识别到这是包内的相对引用,运行正常;但进到PyUtils目录直接跑pytest时,Python会把test_sistema.py当成顶层独立脚本,识别不到它所属的父包,就会报相对导入错误。
可行解决方案
方案1:按Python包规范统一执行路径(改动最小,优先推荐)
不需要改业务代码逻辑,只要调整导入写法和测试执行方式即可:
- 保留sistema.py中的相对导入:
from .strings import String - 修改test_sistema.py中的导入语句,和主脚本的包导入逻辑保持一致:
import PyUtils.sistema as sis - 执行测试时不要进入PyUtils目录,回到scripts项目根目录运行pytest命令:
这种方式下Python会自动把scripts目录加入模块搜索路径,既能正确识别PyUtils为合法Python包,同时兼容主脚本运行、测试执行两种场景,不会出现导入冲突。pytest PyUtils/test_sistema.py
方案2:兼容子目录直接执行pytest的使用习惯
如果不想每次都切到根目录跑测试,习惯进到PyUtils目录直接执行pytest,做3处小调整即可:
- 在PyUtils目录下新建空文件
__init__.py,将目录标记为正式Python包。 - 在PyUtils目录下新建pytest配置文件
conftest.py,写入以下代码把上层项目根目录加入模块搜索路径,让测试运行时能识别到父包:import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent.resolve())) - 修改test_sistema.py中的导入语句为包内相对导入:
调整完成后,上层主脚本调用、根目录执行pytest、PyUtils目录内直接执行pytest三种场景都能正常运行。from . import sistema as sis
注意:不要使用try-except捕获导入错误、同时写两套导入逻辑的写法,这类写法会在包结构调整时触发难以排查的隐式导入问题,维护成本极高,不符合Python包设计规范。
内容的提问来源于stack exchange,提问作者Leandro 86
相关产品推荐
相关产品推荐

