相对导入:
先引入一个顶层包(top-level package)的概念:顶层包是不断变化的,主运行函数所在目录的子目录为顶层包
test/
--main.py : import b.c
--a/
--k.py : print("I'm top level")
--b/
--c.py : from ..a import k from . import f
--f.py : print ('f')
以上层级,其中main.py定为主运行函数,则主运行函数所在目录的子目录为顶层包(a、b),相对导入,不管是from …(两个点) 还是from .(一个点),…(两个点)和.(一个点)所对应的目录均不能超过这个顶层目录,在本例中,c.py中使用了相对导入,其…(两个点)对应test目录,超过了顶层包,而.(一个点)对应b目录,没超过顶层包
相对导入的详细例子:
day21/
glance/
__init__.py # from . import api from . import cmd
api/
__init__.py # from . import policy from . import versions
police.py # print(__name__) from ..cmd import manage manage.main()
versions.py #* print("In grok") *# def create_resource(conf): print('from version.py: ', conf)
cmd/
__init__.py # from . import manage
manage.py # def main() print('from manage.py')
run.py
main.py
相对导入与模块__name__有关
一、执行run.py
1、如果run.py的代码如下:
import api # 用相对路径
- run.py执行时
- run.py的__name__ 等于 main
- police.py的__name__ 等于 api.police
- api成为顶层的包,所以api中的代码模块相对导入最多只能访问到api,api之外的层次结构是不可见的,即cmd不能导入。结果如下:
2、如果run.py的代码如下:
import glance # 用绝对路径
- run.py执行时
- run.py的__name__ 等于 main
- police.py的__name__ 等于glance.api.policy
- glance成为顶层的包,所以api中的代码中的模块相对导入最多只能访问到glance,api能访问到cmd,因此cmd能导入。结果如下:
二、执行main.py
1、main.py的代码
import glance # 只能用绝对路径
- main.py执行时:
- run.py的__name__ 等于 main
- police.py的__name__ 等于 glance.api.policy
- glance成为顶层的包,所以api中的代码中的模块相对导入最多只能访问到glance,api能访问到cmd,因此cmd能导入。结果如下:
如果将run.py当作顶层执行模块(前提:用相对路径)
cmd/ 和 api/ 将成为顶层包,api/中的模块不能用相对导入来导入cmd/包中的模块,因为不能越过顶层包。cmd/、api/ 包中的只能导入本包中及以下的模块
如果将main.py当作顶层执行模块,glance/成为顶层包,api/可以访问到cmd/包,不会报下面的错误
ValueError: attempted relative import beyond top-level package**
注意:
相对导入不能在执行文件中使用
相对导入只能在被导入的模块中使用,使用相对导入,就不需要考虑执行文件到底是谁了,只需要直到模块与模块之间路径的关系