带__init__.py的Python项目中pytest无法导入基础模块问题
问题根源
当mod_1、mod_2目录下存在__init__.py时,它们会被Python识别为project顶级包的子包,形成嵌套包结构。此时object_factory.py是project包下的子模块,而非独立的顶级模块。如果你的测试文件里用import object_factory这种直接导入,Python会在sys.path的顶级目录里找这个模块,自然找不到——因为它属于project包内部。
而移除mod_#下的__init__.py后,mod_1、mod_2变成普通目录,不再是包,object_factory.py就处于sys.path包含的/project目录下,成为顶级模块,所以导入能成功。
解决方案
方案1:使用规范的绝对导入(推荐)
修改测试文件里的导入语句,指定完整的包路径:
from project.object_factory import 你的工厂类名
这种方式完全符合Python包结构规范,不管你在哪个目录运行测试都能正常工作,也方便后续项目扩展。
方案2:切换到父目录运行pytest
进入/package目录(project的父目录),然后运行测试:
cd /package pytest project/mod_1/tests/test_mod_1.py
此时/package会被加入sys.path,project成为顶级包,测试文件里的from project.object_factory import ...就能正常识别。
方案3:用相对导入(不推荐)
给mod_1/tests和mod_2/tests目录也添加__init__.py,把测试目录也变成子包,然后在测试文件里用相对导入:
from ...object_factory import 你的工厂类名
这种方式可读性差,且依赖包结构层级,只适合临时场景,不推荐长期使用。
方案4:保留无__init__.py的结构(仅限简单场景)
如果你的项目不需要把mod_1、mod_2作为包导入到其他模块,可以继续移除mod_#下的__init__.py,保持当前导入方式。但这种方式会限制项目的模块化扩展能力。
内容的提问来源于stack exchange,提问作者KirkD-CO

