详解Python中的相对导入和绝对导入


Posted in Python onJanuary 06, 2017

前言

Python 相对导入与绝对导入,这两个概念是相对于包内导入而言的。包内导入即是包内的模块导入包内部的模块。

Python import 的搜索路径

  1. 在当前目录下搜索该模块
  2. 在环境变量 PYTHONPATH 中指定的路径列表中依次搜索
  3. 在 Python 安装路径的 lib 库中搜索

Python import 的步骤

python 所有加载的模块信息都存放在 sys.modules 结构中,当 import 一个模块时,会按如下步骤来进行

  1. 如果是 import A,检查 sys.modules 中是否已经有 A,如果有则不加载,如果没有则为 A 创建 module 对象,并加载 A
  2. 如果是 from A import B,先为 A 创建 module 对象,再解析A,从中寻找B并填充到 A 的 __dict__

相对导入与绝对导入

绝对导入的格式为 import A.Bfrom A import B,相对导入格式为 from . import Bfrom ..A import B,.代表当前模块,..代表上层模块,...代表上上层模块,依次类推。

相对导入可以避免硬编码带来的维护问题,例如我们改了某一顶层包的名,那么其子包所有的导入就都不能用了。但是 存在相对导入语句的模块,不能直接运行,否则会有异常:

ValueError: Attempted relative import in non-package

这是什么原因呢?我们需要先来了解下导入模块时的一些规则:

在没有明确指定包结构的情况下,Python 是根据 __name__ 来决定一个模块在包中的结构的,如果是 __main__ 则它本身是顶层模块,没有包结构,如果是A.B.C 结构,那么顶层模块是 A。基本上遵循这样的原则:

  1. 如果是绝对导入,一个模块只能导入自身的子模块或和它的顶层模块同级别的模块及其子模块
  2. 如果是相对导入,一个模块必须有包结构且只能导入它的顶层模块内部的模块

如果一个模块被直接运行,则它自己为顶层模块,不存在层次结构,所以找不到其他的相对路径。

Python2.x 缺省为相对路径导入,Python3.x 缺省为绝对路径导入。绝对导入可以避免导入子包覆盖掉标准库模块(由于名字相同,发生冲突)。如果在 Python2.x 中要默认使用绝对导入,可以在文件开头加入如下语句:

from __future__ import absolute_import

from __future__ import absolute_import

这句 import 并不是指将所有的导入视为绝对导入,而是指禁用 implicit relative import(隐式相对导入), 但并不会禁掉 explicit relative import(显示相对导入)。

那么到底什么是隐式相对导入,什么又是显示的相对导入呢?我们来看一个例子,假设有如下包结构:

thing
├── books
│ ├── adventure.py
│ ├── history.py
│ ├── horror.py
│ ├── __init__.py
│ └── lovestory.py
├── furniture
│ ├── armchair.py
│ ├── bench.py
│ ├── __init__.py
│ ├── screen.py
│ └── stool.py
└── __init__.py

那么如果在 stool 中引用 bench,则有如下几种方式:

import bench     # 此为 implicit relative import
from . import bench   # 此为 explicit relative import
from furniture import bench # 此为 absolute import

隐式相对就是没有告诉解释器相对于谁,但默认相对与当前模块;而显示相对则明确告诉解释器相对于谁来导入。以上导入方式的第三种,才是官方推荐的,第一种是官方强烈不推荐的,Python3 中已经被废弃,这种方式只能用于导入 path 中的模块。

相对与绝对仅针对包内导入而言

最后再次强调,相对导入与绝对导入仅针对于包内导入而言,要不然本文所讨论的内容就没有意义。所谓的包,就是包含 __init__.py 文件的目录,该文件在包导入时会被首先执行,该文件可以为空,也可以在其中加入任意合法的 Python 代码。

相对导入可以避免硬编码,对于包的维护是友好的。绝对导入可以避免与标准库命名的冲突,实际上也不推荐自定义模块与标准库命令相同。

前面提到含有相对导入的模块不能被直接运行,实际上含有绝对导入的模块也不能被直接运行,会出现 ImportError:

ImportError: No module named XXX

这与绝对导入时是一样的原因。要运行包中包含绝对导入和相对导入的模块,可以用 python -m A.B.C 告诉解释器模块的层次结构。

有人可能会问:假如有两个模块 a.py 和 b.py 放在同一个目录下,为什么能在 b.py 中 import a 呢?

这是因为这两个文件所在的目录不是一个包,那么每一个 python 文件都是一个独立的、可以直接被其他模块导入的模块,就像你导入标准库一样,它们不存在相对导入和绝对导入的问题。相对导入与绝对导入仅用于包内部。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能有一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
Python中获取对象信息的方法
Apr 27 Python
win系统下为Python3.5安装flask-mongoengine 库
Dec 20 Python
对Python Pexpect 模块的使用说明详解
Feb 14 Python
不到40行代码用Python实现一个简单的推荐系统
May 10 Python
python同时替换多个字符串方法示例
Sep 17 Python
使用python实现希尔、计数、基数基础排序的代码
Dec 25 Python
Anaconda+VSCode配置tensorflow开发环境的教程详解
Mar 30 Python
matplotlib subplot绘制多个子图的方法示例
Jul 28 Python
Python pymysql模块安装并操作过程解析
Oct 13 Python
Python实现哲学家就餐问题实例代码
Nov 09 Python
利用Python函数实现一个万历表完整示例
Jan 23 Python
python利用proxybroker构建爬虫免费IP代理池的实现
Feb 21 Python
Python中取整的几种方法小结
Jan 06 #Python
Python正则表达式实现截取成对括号的方法
Jan 06 #Python
关于Python元祖,列表,字典,集合的比较
Jan 06 #Python
Python线程指南详细介绍
Jan 05 #Python
Python爬虫代理IP池实现方法
Jan 05 #Python
在 Python 应用中使用 MongoDB的方法
Jan 05 #Python
深入理解python对json的操作总结
Jan 05 #Python
You might like
destoon实现资讯信息前面调用它所属分类的方法
2014/07/15 PHP
javascript预览上传图片发现的问题的解决方法
2010/11/25 Javascript
客户端限制只能上传jpg格式图片的js代码
2010/12/09 Javascript
关于jquery的多个选择器的使用示例
2013/10/18 Javascript
深入浅析react native es6语法
2015/12/09 Javascript
快速学习AngularJs HTTP响应拦截器
2015/12/31 Javascript
jQuery中ajax错误调试分析
2016/12/01 Javascript
bootstrap modal+gridview实现弹出框效果
2017/08/15 Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
2018/02/09 Javascript
vue实现循环切换动画
2018/10/17 Javascript
JavaScript实现简单音乐播放器
2020/04/17 Javascript
vue中v-text / v-html使用实例代码详解
2019/04/02 Javascript
详解vue-flickity的fullScreen功能实现
2020/04/07 Javascript
解决element-ui的下拉框有值却无法选中的情况
2020/11/07 Javascript
[05:49]2014DOTA2TI4正赛第二日综述 昔日冠军纷纷落马 VG LGD占尽先机
2014/07/20 DOTA
[01:20:06]TNC vs VG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python判断变量是否已经定义的方法
2014/08/18 Python
使用Python的Twisted框架构建非阻塞下载程序的实例教程
2016/05/25 Python
简单谈谈python的反射机制
2016/06/28 Python
Django 实现购物车功能的示例代码
2018/10/08 Python
python 循环读取txt文档 并转换成csv的方法
2018/10/26 Python
详解使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件
2019/08/23 Python
Python collections中的双向队列deque简单介绍详解
2019/11/04 Python
python误差棒图errorbar()函数实例解析
2020/02/11 Python
韩国江南富人区高端时尚百货商场:Galleria(格乐丽雅)
2018/03/27 全球购物
英国在线发型和美容产品商店:Beauty Cutie
2019/04/27 全球购物
馥蕾诗美国官网:Fresh美国
2019/10/09 全球购物
Collection和Collections的区别
2016/05/02 面试题
介绍一下SQL Server的全文索引
2013/08/15 面试题
酒店人事专员岗位职责
2013/12/19 职场文书
乡镇领导班子四风对照检查材料
2014/09/27 职场文书
管理失职检讨书范文
2015/05/05 职场文书
2015年语文教师工作总结
2015/05/25 职场文书
优秀党员主要事迹范文
2015/11/05 职场文书
导游词之无锡梅园
2019/11/28 职场文书
话题作文之呼唤
2019/12/18 职场文书