Python 3.6中unittest为何仍要求存在__init__.py?
关于Python 3.6 unittest discover 路径分隔符导致的问题分析
这确实是Python 3.6版本unittest模块中的一个已知问题,本质上是测试发现逻辑没有完全适配PEP 420引入的命名空间包规范导致的,完全可以认定是一个bug。
问题根源
你找到的/usr/lib/python3.6/unittest/loader.py:286那行代码:
is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
是问题的核心:它硬把“存在__init__.py”作为目录可导入的判定条件,但PEP 420在Python 3.3就已经取消了命名空间包对__init__.py的强制要求。
而两种命令的差异原因在于:
- 当使用
.作为分隔符(比如tests.foo)时,unittest会把它当作模块路径处理,通过Python的import机制去查找测试模块,这时候会遵循PEP 420的规范,不需要__init__.py也能识别; - 当使用
/作为分隔符(比如tests/foo)时,unittest会直接把它当作文件系统路径处理,触发上述那行代码的检查,没有__init__.py就会判定为“不可导入”,抛出ImportError。
解决办法
如果你暂时无法升级Python版本,有两个可行的临时方案:
- 在测试目录下添加一个空的
__init__.py文件,虽然不符合纯命名空间包的规范,但能兼容旧版本unittest的检查逻辑; - 始终使用
.作为路径分隔符来指定测试模块路径,避开文件系统路径的检查逻辑。
后续修复情况
这个问题在Python 3.7及以后的版本中已经被官方修复了——unittest的测试发现逻辑被更新,不再强制依赖__init__.py来识别可导入的测试目录,完全适配了PEP 420的规范。
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

