Python3同目录相对导入报错原因及语法支持性咨询
首先明确:Python 3完全支持相对导入语法,你遇到的报错并非语法不支持,而是运行脚本的方式不符合相对导入的要求。
报错原因
当你直接运行test/test.py(比如执行python test/test.py)时,Python会把这个脚本当作顶层主模块来执行,此时它的模块名被设为__main__,而不是test.test。相对导入中的.代表当前模块的父模块,但作为顶层主模块运行时,它并没有处于包的层级结构中(或者说它的父模块不存在),因此Python无法找到line模块,从而抛出ImportError。
至于import line能成功,是因为直接运行脚本时,Python会自动将脚本所在的目录(即test/目录)添加到sys.path的最前端,此时import line会优先从当前目录加载line.py,而非标准库。但正如你担心的,这种做法存在风险——如果未来Python标准库新增了名为line的模块,你的代码会意外导入标准库模块,引发难以排查的bug。
正确的解决方法
要让相对导入生效,你需要将test作为一个包来加载,而非直接运行包内的test.py,具体操作如下:
- 切换到
test目录的上级目录(也就是包含test文件夹的那个目录) - 执行命令:
python -m test.test
此时Python会将test.test当作包内的子模块加载,模块名不再是__main__,而是test.test,相对导入中的.就代表test包,自然能成功导入line模块。
你也可以考虑调整目录结构(比如将测试脚本移到包外),或者使用from test import line这类绝对导入,但相对导入在包内代码组织中是更规范的做法。
内容的提问来源于stack exchange,提问作者doUWannaBuildASnowMan

