为何Python中import ...与from x import y语法在该场景下表现差异巨大?
import和from...import在导入类时表现不同? 我的包结构
srcsrc/main.pysrc/package1src/package1/__init__.pysrc/package1/module1.pysrc/package1/module2.py
其中module2是module1的子类,src/package1/module2.py中的代码为:
from package1.module1 import SomeClassFromModule1 class SomeClassFromModule2(SomeClassFromModule1): # 子类实现逻辑 pass
问题场景
在src/main.py中,两种导入方式出现了明显差异:
选项1(可正常运行)
from package1.module2 import SomeClassFromModule2 def main(): some_name = SomeClassFromModule2() if __name__ == "__main__": main()
选项2(运行报错)
import package1.module2.SomeClassFromModule2 def main(): some_name = package1.module2.SomeClassFromModule2() if __name__ == "__main__": main()
触发的错误提示:
ModuleNotFoundError: No module named 'package1.module2.SomeClassFromModule2'; 'package1.module2' is not a package
差异原因解释
这两种导入语法的核心区别在于它们的作用对象和逻辑完全不同:
from ... import ...的工作逻辑from package1.module2 import SomeClassFromModule2是先定位到package1.module2这个**.py模块文件**,然后直接从该模块的内部命名空间中提取SomeClassFromModule2这个类对象,将它导入到当前脚本的命名空间里。它明确知道package1.module2是一个模块,而非子包,所以会去读取模块内定义的成员(类、函数、变量等)。import ...的工作逻辑import package1.module2.SomeClassFromModule2则是把整个链式路径的每一段都当作包或独立模块来处理。Python的import语句要求路径中的每个节点必须是:要么是包含__init__.py的包目录,要么是.py格式的模块文件。但SomeClassFromModule2只是module2.py里定义的一个类,并不是一个独立的模块或包,Python会尝试寻找名为package1.module2.SomeClassFromModule2的模块文件或包目录,自然找不到,因此抛出ModuleNotFoundError。
替代的import写法
如果想用import语法实现同样效果,应该先导入模块本身,再通过模块命名空间访问类:
import package1.module2 def main(): some_name = package1.module2.SomeClassFromModule2() if __name__ == "__main__": main()
这样Python会先导入package1.module2模块,你再通过模块的命名空间去访问它内部的类,就能正常运行了。
内容的提问来源于stack exchange,提问作者CodingButStillAlive

