说明
我在调试代码的时候,发现上面的print打印了两次,如果将图片中的
from aaa.F import Cat 改成 from F import Cat 则print只会打印一次。这是为什么呢?
结论
from aaa.bbb.ccc import *
则用 ‘.’ 分割的每个包中的 init.py 都会执行一次,顺序依次为:aaa->bbb->ccc
这个特性十分重要,一不小心容易重复打印。
主模块
直接运行的文件称为 主模块, 主模块中 以及其同级 模块都不能用相对导入否则报错。例子如下
# 案例一:主模块同级模块使用相对导入
TestModule/
├── __init__.py # 这个文件其实未起作用
├── main.py # import brother1; print(__name__)
├── brother1.py # from . import brother2; print(__name__) #同级模块使用了相对导入则一定报错
└── brother2.py # print(__name__)
案例二:主模块使用相对导入
TestModule/
├── __init__.py # 这个文件其实未起作用
├── main.py # from . import brother1; print(__name__)
├── brother1.py # import brother2; print(__name__)
└── brother2.py # print(__name__)
主模块所在位置不会被python认为是包
TestModule/
├── main.py
| from Tom import tom; print(__name__) # 这是主模块
├── __init__.py
├── Tom
│ ├── __init__.py # print(__name__)
│ ├── tom.py from . import tom_brother; rom ..Kate import kate; print(__name__) ## 相对导入父级包,但是运行main.py时候,父级已经不被视为包了,报错
│ └── tom_brother.py # print(__name__)
└── Kate
├── __init__.py # print(__name__)
└── kate.py # print(__name__)
当运行main.py的时候,则TestModule会自动失去包的概念,则其他模块有 用相对路径 来导入main.py所在路径下的包时会报错。因为main.py所在位置已经不被识别为包了。
https://zhuanlan.zhihu.com/p/416867942
import 绝对路径问题
如果要在bbb中的__init__.py 中使用aaa中的tudouya.py,则用from aaa import tudouya 报错,但是用from app.aaa import tudouya 不报错
这是因为:
包的导入是基于模块的绝对路径的。
当使用from aaa import tudouya
时,Python会尝试在当前目录下找到aaa模块,但是在当前目录下并没有aaa模块,所以会报错。 而
当使用from app.aaa import tudouya
Python会根据绝对路径去寻找aaa模块,这时就可以成功导入tudouya模块。
因此,要在bbb中的__init__.py 中使用aaa中的tudouya.py,应该使用from app.aaa import tudouya。