ImportError: attempted relative import with no known parent package 彻底搞懂python的import规则
- 一个复杂的 Python 项目应该使用包(package)来组织代码,结合相对和绝对引入来管理模块之间的依赖关系。
- 每个 .py 文件可以被视为一个模块(module),而模块是组织和重用代码的基本单位;每个含有
__init__.py
的文件夹就是一个包(package),包是组织和管理模块的方式。 - 当在普通文件夹下存在 .py 文件时,可以使用文件名作为绝对引入的方式直接引入该模块,并且可以直接运行该文件。
- 在同一个包(package)下的 .py 文件之间应该使用相对引入来导入模块。使用相对引入的模块不应该也不能直接运行,而是需要在包的外部通过绝对引入来引入和使用它。
- 所有的相对导入最终都会被解析为绝对导入路径,以确保模块的导入正确性和一致性。
- 当运行一个文件时,被直接运行的文件会被认为是主模块(name == “main” 为 True),主模块的引入以及它引入的模块中的导入语句都是相对于主模块所在目录进行查找和解析的。
例子
不使用包(package)的引入。
目录结构如下:
demo是一个文件夹,包含module1.py和module2.py。
name="module1"
from module1 import nameif __name__=="__main__":print(name)
这样可以直接运行module2.py
打印"moudule1"。
而如果修改module2.py为如下:
from .module1 import nameif __name__ == '__main__': print(name)
再直接运行会报错:
ImportError: attempted relative import with no known parent package
这是因为使用.
的这种方式是相对引入,使用相对引入的模块不能直接运行。
使用包(package)的引入
目录结构如下:
我们在demo
目录中新增了一个空的__init__.py
,这样demo
就是一个包了。
main.py
中使用绝对引入,引入module2
的函数
from demo.module2 import printNameif __name__ == '__main__': printName()
来看module2的各种使用情况,结果放在注释中,可以解除注释自行尝试。
# 情况1# from .module1 import name # """# 相对引入,直接运行这个文件报错# ImportError: attempted relative import with no known parent package# 外层的main.py可以运行。# """# 情况2# from demo.module1 import name# """# 绝对引入,但是直接运行报错,当前目录找不到demo包# 外层的main.py可以运行。# """#情况3# from module1 import name# """# 绝对引入,可以直接运行# 外层的main运行报错,找不到module1# 因为执行main的时候是从main所在目录直接找module1# """def printName(): print(name)if __name__ == '__main__': printName()
好的我们现在把main.py所在目录
也变成一个包,同时修改为相对引入如图:
现在运行main.py
报错,这还是是因为使用相对引入导致的,因为你使用相对引入就不能当作主模块直接运行。
包名冲突的情况
目录结构和main.py
如图:
再来看module2
的各种情况
# 情况1# from .module1 import name # """# 直接运行报错# 相对引入,直接运行这个文件报错# 外层的main.py可以运行,输出外层的# # """# 情况2# from demo.module1 import name# """# 直接运行则为绝对引入,输出子包demo的module1的name: "inner_module1"# 外层的main.py可以运行,这是这里的引入就是相对引入了,输出外层的module1的name : "module1"# """# 情况3# from .demo.module1 import name# """# 直接运行报错# 外层的main.py可以运行,为相对引入,输出子包demo的module1的name: "inner_module1"# """def printName(): print(name)if __name__ == '__main__': printName()
来源地址:https://blog.csdn.net/m0_52726759/article/details/131317982
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341