注册 登录
Python基础教程

第一章: 环境搭建,安装Python

第二章: 挑选一款趁手的IDE

第三章: 计算机基础知识

第四章: 命令行基础知识

第五章: 从全局把握Python

第六章: Python语言基础

第七章: Python流程控制

第八章: Python数据类型与运算

第九章: Python字符串类型

第十章: Python列表类型

第十一章: Python元祖类型

第十二章: Python字典类型

第十三章: Python集合类型

第十四章: Python函数处理

第十五章: Python文件处理

第十六章: Python面向对象

第十七章: Python异常处理

第十八章: Python模块处理

第十九章: Python项目实战

首页 > Python基础教程 > 第十八章: Python模块处理 > 18.4节:模块的绝对导入与相对导入

18.4节:模块的绝对导入与相对导入

薯条老师 2020-05-26 14:00:59 210387 0

编辑 收藏

教程引言:

系统地讲解计算机基础知识,Python的基础知识, 高级知识。关注微信公众号[薯条编程],领取该教程的PDF电子书:《Python零基础入门指南》。

18.4.1 绝对导入

模块的绝对导入是指从当前顶层的package位置处开始导入。这里涉及到一个概念:顶层package。
那么,什么是顶层package?

同学们请看如下的一种目录结构:

└── main.py
└── utils
   ├──__init__.py
   ├──calc_max.py
   ├──arithmetic
   │   ├── __init__.py
   │   └── add.py

顶层package是指在包的层级结构中,位于最上层的包。在上文的目录结构中,项目入口文件为main.py, utils是一个包,arithmetic是utils的子级包。在main.py中导入arithmetic包中的add模块时,则当前顶层的package是utils, 使用绝对导入的语法为:from utils.arithmetic import add。表示从utils包下的arithmetic包中导出add模块。

访问package下面的子package,使用.符号来进行访问。假设最顶层的package为A,A下面的子package为B,B下面的子package为C,则导出B中模块的写法为from A.B import module。导出C中模块的写法为 from A.B.C import module,以此类推。

在calc_max.py中需要导入arithmetic包中的add模块时,则当前顶层的package就是arithmetic, 使用绝对导入的语法为:from arithmetic import add。

18.4.2 相对导入

(1) 前缀点号

模块的相对导入是指在package内部,相对于当前位置进行导入。在相对导入语法中需要使用前缀点号.。单个点号.表示当前目录,两个点号..表示父目录,三个点号...表示父目录的父目录,以此类推。读者请看以下的一种目录结构:
└── main.py
└── utils
   ├──__init__.py
   ├──log.py
   ├──accumulate.py
   ├──arithmetic
   │   ├── __init__.py
   │   └── add.py

在上文的目录结构中,顶层package为utils。假设在log.py中想要导入arithmetic包中的add模块,则语法为:from .arithmetic import add,表示在当前目录中的arithmetic包中导出add模块。如果在arithmetic包中的add.py中导入utils包中的accumulate模块,则语法为:from  .. import accumulate,表示从父目录中导入accumulate模块。

(2) 顶层作用域

在进行相对导入时不能超出当前package的顶层作用域,否则会抛出ValueError的异常,指示超出了顶层package的作用域。

读者看如下的一种包结构:
└── dal
   ├──__init__.py
   ├──conn.py
└── utils
   ├──__init__.py
   ├──log.py

 

在上文的包结构中,一共有两个package,分别是dal与utils。对于log.py来说,utils包就是其顶层package,对于conn.py来说,dal包就是其顶层package。 直接运行模块时,python会将该模块所在的目录, 作为当前目录下的package和所有子package的顶层作用域。同学们继续看以下的一种目录结构:
└── main.py
└── utils
   ├──__init__.py
   ├──log.py
   ├──accumulate.py
   ├──arithmetic
   │    ├── __init__.py
   │    └── add.py

直接运行main.py时,main.py所在的目录就作为包结构的顶层作用域,此时在utils包和arithmetic包中的模块执行相对导入都会正常运行。如果在arithmetic目录中运行add.py,则arithmetic目录就作为顶层作用域,此时在add模块中相对导入utils包中的log模块,会抛出ValueError的错误异常,指示超出了包结构的顶层作用域。

18.4.3 使用什么方式进行导入?

使用什么方式进行导入,得分析这两种导入方式的优缺点。先从实例入手,请读者分析以下的一种多层嵌套的目录结构:
└── main.py
└── utils
   ├──__init__.py
   ├──arithmetic
   │   ├── __init__.py
   │   └──common
               ├──__init__.py
               ├──add.py

 

在main.py中使用绝对导入的方式,导入common中的add模块,语法为:from utils.arithmetic.common import add。这种写法的优点在于,只需查看导入语句,就能清晰地知道add模块的具体位置。但如果嵌套的目录过深,那么绝对导入会变得非常冗长,而且在其中任何一个包名发生更改的情况下,使用了绝对导入的源程序都得修改,例如将common修改为simple,则在代码文件中必须同步地将from utils.arithmetic.common import add修改为from utils.arithmetic.simple import add

在企业开发中,嵌套的目录过深,这属于在程序设计上应该规避的问题。在无特殊情况下,目录通常不应该超过3层,所以在大部分情况下,使用绝对导入并不会带来句法冗长的问题。程序员要注意的是包名的变动,一旦包名发生变动,那么所有使用了绝对导入的文件都需要进行修改。

相对导入是基于当前位置来进行模块的导入,所以即使模块名发生变动,也无需修改源代码。比如以下的一种包结构:
└── main.py
└── utils
   ├──__init__.py
   ├──log.py
   ├──accumulate.py
   ├──arithmetic
   │   ├── __init__.py
   │   └── add.py

在add.py中使用相对导入的形式来导入utils包中的accumulate模块,语法形式为:from .. import accumulate。即使utils包名或arithmetic包名发生了更改,accumulate模块也能正常导入。
将main.py所在的目录保存在PYTHONPATH或sys.path中,此时在add.py中也可以通过绝对导入的方式导入utils包中的accumulate模块。

相对导入的缺点是容易造成代码的混乱和可读性变差,例如下面的一种导入结构:

from .. import A.function
from ... import B.function
from ..C import D.function
Python中的默认导入方式为绝对导入,因其句法清晰,直接,企业开发中也通常将绝对导入作为首选。PEP8规范中也明确建议采用绝对导入的方式来进行模块导入。

18.4.4 知识要点

(1) 模块的绝对导入是指从当前顶层的package位置处开始导入
(2) 模块的相对导入是指在package内部,相对于当前位置进行导入
(3) Python中的默认导入方式为绝对导入,因为其句法清晰,直接,企业开发中也通常将绝对导入作为首选

18.4.5 高薪就业班

(1) Python后端工程师高薪就业班,月薪8K-15K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十万,免费领取课程大纲
(3) Java后端开发工程师高薪就业班,月薪8K-20K, 免费领取课程大纲
(4) Python大数据工程师就业班,月薪12K-25K,免费领取课程大纲

扫码免费领取学习资料:


欢迎 发表评论:

请登录

忘记密码我要注册

注册账号

已有账号?请登录