详解Python import机制(上):import中的基本概念

点击阅读原文,查看精彩日程!


作者 |  ayuliao

来源 | hackpython(ID: hackpython

简介

简单来看,import机制可以导入我们需要使用的库,避免代码重复,使用方便,可谓是编写Python时最常使用写法,但我们了解import吗?


import其实有很多容易混淆的概念以及可以实现很多非常有趣的玩法,本篇文章抛砖引玉,聊聊import


需注意,Python2与Python3的import机制有较大差别,主要体现在两个节点,Python2.6之前使用relative import(相对导入)作为默认import机制,Python2.6之后使用absolute import(绝对导入)作为默认import机制;Python3.3出现命名空间包的概念。


简单而言,Python3.7与Python2.7在import机制上有较大差异,这里以Python3.7为基准进行讨论。

模块、常规包与命名空间包

「模块」、「常规包」与「命名空间包」是理解import机制绕不开的概念。

「模块」:一个以「.py」为后缀的文件就是一个模块「常规包」:「__init__.py」所在目录就是一个常规包「命名空间包」:命名空间包是一种虚拟的概念,它由多个子包构成,这些子包可以在任意位置,可以为zip中的文件或网络上的文件,这些子包在概念上是一个整体,这个整体就是一个命名空间包

「常规包」与「命名空间包」的概念在PEP420被提出,在Python3.3及之后的Python版本中实现,此前只有「常规包」这一种包。


import导入系统

通过import机制,我们可以使用导入模块内的代码。

import是最常用的导入机制,但并不是唯一的方式,importlib模块以及内置的__import__()方法都可以实现模块的导入。

import语句做的是两个操作

1.搜索操作:在相应的路径中搜索指定名称的模块2.绑定操作:将搜索到的结果绑定到当前作用域对应的名称上(即创建module对象,并初始化)

通过阅读Python官方文档可知,import的搜索操作通过__import__()方法实现,而绑定操作只有import语句才能做到。

当某个模块初次被import时,Python会在相应的路径去搜索该模块,如果模块存在,则在当前作用域下创建一个module对象并进行初始化,如果未找到,则抛出 ModuleNotFoundError。

import在导入模块时,会根据sys.path中定义的路径来搜索对应的模块,sys.path是一个list,import时会先从sys.path中下标为0的路径开始搜索,我们可以将需要的路径添加到sys.path。

如果我们没有修改,sys.path中默认的路径为:

  • 1.当前目录的路径

  • 2.环境变量PYTHONPATH中指定的路径列表

  • 3.Python安装路径的lib目录所在路径

要修改搜索路径有3种方式:

  • 1.动态修改sys.path,因为sys.path为list,所以我们可以很轻松的操作list实现搜索路径的修改。这种方式只会对当前项目临时生效

  • 2.修改PYTHONPATH环境变量,这种方式会永久生效,而且所有的Python项目都会受到影响,因为Python程序启动时会自动去读取该环境良好的值。

  • 3.增加.pth后缀的文件。在sys.path已有的某一个目录下添加.pth后缀的配置文件,该文件的内容就是要添加的搜索路径,Python在遍历已有目录的过程中,如果遇到.pth文件,就会将其中的路径添加到sys.path中。

Python中定义了多种搜索策略去搜索相应的模块,而这些策略可以通过importlib等提供的各类hook进行修改实现一些有趣的效果。

在Python3.3之后,所有的模块导入机制都会通过「sys.meta_path」暴露,不会在有任何隐式导入机制。

 
 

import形式

import主要有两种形式

1.import xxx

2.from xxx import xxx

可以看到下面的例子:

 
 

可以看出,第2行与第3行的区别在于是否使用from,其背后的规则是:

  • 1.单独使用import时,import后面只能接模块或包(常规包或命名空间包)

  • 2.使用from xxx import xxx 时,from后只能接模块或包,而此时import后可以接任何变量(模块、包或模块中具体的方法)

在导入模块的过程中,首先会搜索sys.modules中内容,sys.modules是模块的缓存,其中包括了所有此前导入的模块。

  • 1.使用的是 import A, 此时会先检查sys.moduels中是否存在A,如果存在,则不会再去搜索加载,而是直接从缓存中取来用,如果没有,则搜索模块并进行绑定操作,随后便将其加载到sys.modules中

  • 2.使用的是 from A import B,此时依旧会先检查A并进行相同的操作,随后获得A的module对象后,从中解析并寻找B然后再填充到A的__dict__结构中,从而实现不用标明来自于A,直接通过B的名称就可直接使用的B的效果。


相对导入与绝对导入

当我们import导入模块或包时,Python提供两种导入方式:

1.相对导入 relative import2.绝对导入 absolute import

在Python2.6之前,Python默认使用的相对导入,而Python2.6之后,以绝对导入为默认使用的导入方式。

这两个概念与相对路径、绝对路径的概念有些相似,几个具体的例子:

1.绝对导入格式为:import A.B.C 或者 form A.B import C2.相对导入格式为:from . import B 或 from ..A import B,其中.表示当前模块,..表示上层模块(与相对路径概念类似)

在开发第三方模块时,通常使用相对导入的形式,这可以有效避免硬编码带来的问题,比如在开发过程中,我们修改了某个文件的名称,此时,使用绝对导入形式的import就需要修改相应的名称。这其实也不是绝对的,当包的结构发生改变时,相对导入就会出现问题,当相对模块名称的改变而言,目录结构的改变出现概率会小一些。


(本文由Python大本营转载,转载请联系原作者)

精彩推荐


早鸟票限量5折
2019 中国大数据技术大会(BDTC)再度来袭!豪华 主席 阵容及 百位技术专家 齐聚, 15 场 精选 专题技术和行业论坛, 超强干货+技术剖析+行业实践立体解读 ,深入解析热门技术在行业中的实践落地。

640?wx_fmt=jpeg

推荐阅读

640?wx_fmt=png
你点的每个“在看”,我都认真当成了喜欢

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值