Python相对导入失效:指定根包名仍报超出顶级包错误
报错核心原因
你执行python -m unittest discover package时,unittest的测试发现机制会将package目录下的子目录(integration、unit)直接当作顶级Python包来导入测试模块。此时测试模块里的from ..util.foo import run_foo试图从当前顶级包(比如integration)往上跳一级,这超出了Python允许的顶级包范围,因此触发ImportError: attempted relative import beyond top-level package错误。
简言之:原本integration和unit是package的子包,但discover package的导入逻辑没有把package作为它们的父包,导致相对导入的层级判断出错。
两种可行的解决办法
方法1:调整命令,让package作为父包被识别
在UnittestDiscovery目录下执行以下命令,不要指定package参数:
python -m unittest discover
此时unittest会从当前目录开始查找测试,package会被当作父包,测试模块会被正确导入为package.integration.test_some_integration、package.unit.test_some_unit,相对导入..util就能正确指向package.util。
方法2:改用绝对导入
把测试模块里的相对导入替换为绝对导入:
# 替换原来的 from ..util.foo import run_foo from package.util.foo import run_foo
修改后可继续执行原命令python -m unittest discover package,因为绝对导入会直接从sys.path(当前UnittestDiscovery目录默认在其中)找到package包,无需依赖相对导入的层级判断。
内容的提问来源于stack exchange,提问作者user118967

