python深入之包内的模块导入

关于包内导入的概念和分类

(1)包内导入:即在一个包的内部,存在某个模块导入了其他在该包内部的模块

(2)包内导入分类:绝对导入和相对导入。绝对导入即是使用绝对路径进行导入,如import 包.模块;相对导入即是使用“.” 或“..”来表示相对路径进行导入,“.”表示根据模块名称获取的当前目录,“..”表示根据模块名称获取的上级目录,如from . import A

关于两种形式解决的包内导入所产生的问题

(1)绝对导入解决模块的嵌套导入问题:

问题陈述:假设有一个包p,一个外部模块test,包内有两个个模块p1和p2,需求是在模块test中导入p1,再在p1中导入p2

错误方案:首先,在p1中导入p2,import p2,由于p1和p2位于同一个包中,不会报错;然后在test中导入p1,import p.p1,这时就会出问题,报错说没有一个模块名称为p2

原因:模块的导入路径位于sys.path路径列表,当使用解释器执行一个文件时,就会确定当前文件所在的目录,并将该目录放入sys.path中的当前目录位置,添加过之后,随着test文件执行的后续模块导入也会遵循这个sys.path路径列表。这里首先执行test文件,sys.path中的当前目录就变成了test文件所在的目录,这时,执行p1文件,导入p2模块时,就会到sys.path中的当前目录即test文件所在的目录中寻找p2,但test是包外模块,在它所在的目录下不可能找到p包内的模块,所以这里就会报错

正确方案:在p1中导入p2时使用绝对路径导入,即import p.p2或者from p import p2,由于p包与test文件在同一个目录下,所以在sys.path中的当前目录中可以找到包p,然后从p中再来找到p2

(2)相对导入解决包名修改导致的内部使用绝对路径导入模块的方式跟着修改的问题

问题陈述:在上述正确方案中存在一个问题,即如果包内导入涉及很多模块的导入,使用绝对路径导入的话,每一次导入都要写包名p,一旦包的名称被改掉了,这些导入语句就都要跟着修改,工作量很大

解决方案:使用相对路径进行导入,形式为from . import p2,即根据模块名称获取当前目录。

重点描述:当一个模块直接以脚本的形式进行执行时,其名称为__main__,如是以模块的形式进行加载的(被导入),那么其名称是由加载的路径决定的,如包名.包名.模块名。所以上述的当前目录和上级目录不能单纯的认为是模块文件所在的当前目录和上级目录,这里是根据模块名称获取的,如p2是被p1导入的,那么执行p1,这时p2的模块名称是其路径,即p.p2,那么“.”代表的当前目录就是p,而使用“..”时就会报错,因为p已经是p2的最上级,没有其他,而不是在系统目录中的更上一级

关于隐式相对路径和总结

(1)在python3之前的版本中,使用的都是隐式的相对路径,即模块的嵌套导入问题在python3之前的版本中不存在,其中的import p2就相当于from . import p2

(2)解决方案是在模块最前面加入from __future__ import absolute_import语句,就可以消除隐式相对导入形式

(3)总结:在包外进行导入时,用绝对导入方式,在包内进行导入时,用相对导入方式

猜你喜欢

转载自blog.csdn.net/zx870121209/article/details/81540353
今日推荐