IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python模块导入详解 -> 正文阅读

[Python知识库]python模块导入详解

目录

包和模块

模块导入

绝对导入

sys.modules

sys.meta_path

sys.path

相对导入

__init__.py相对导入

mian脚本中的相对导入

Reference


包和模块

????????我们可以在一个脚本中定义变量、函数和类,并添加逻辑,但是当某个项目具有复杂的逻辑时,我们希望把这些逻辑分解成不同的脚本,并以一定的合理的方式组织成层级结构,这种具有层级结构的包含脚本的文件夹就称为包。

????????模块通常指的是定义了变量、函数和类的脚本。但是实际上,包也属于模块的一种,区分一个模块到底是包还是某个具体的脚本,就看该模块是否具有__path__属性,具有__path__属性的模块称为包,没有__path__属性的模块就是我们最长见到的常规脚本。

????????在python3.3之前,要组成一个包,还必须在顶层目录开始,每一层结构目录中,都必须包含__init__.py文件,但是在python3.3开始,可以没有__init__.py文件。上述中,当我们说包是模块时,我们说的这个包指的就是其目录下的__init__.py初始化文件,这一点,可以通过在_init__.py中打印出__name__属性验证,即__init__.py文件的__name__属性就是对应的包名。

模块导入

? ? ? ? 当导入一个模块时,该模块会被执行,当模块是一个包时,根据上述,该包实际上就是该包下的__init__.py文件,所以导入包时,该包对应的__init__.py文件会被执行。当进行类似import A.B.C或者from A.B import C的导入时,会依次执行A、B下的初始化文件,当然如果C依然是一个子包的话,C下的初始化文件也会被执行。

? ? ? ? 这里需要强调一下import语句和from xxx import yyy语句的一点重要区别,import语句后面跟随的必须是模块,但是from xxx import yyy语句中,yyy不一定是模块,也可以是变量、函数或者类。

????????模块导入的方式分为绝对导入和相对导入。

绝对导入

????????在python3开始,绝对导入指的就是import A或者from A import B这种语句。那么,当python在执行import A语句或者from A import B语句时,背后到底做了哪些事情呢?即python到底时如何去查找对应的模块的呢?

sys.modules

? ? ? ? 首先,由于启动python解释器时,python会自己预导入一些内置和标准模块,并把这些被导入的模块记录在sys.modules中,因此,当导入一个模块时,python会先到sys.modules中查找,如果可以找到,那么直接提取对应的模块,如果找不到,则继续下一步查找。

sys.meta_path

? ? ? ? 接下来,python会直接按照sys.meta_path中各个查找器的顺序去查找模块,sys.meta_path是一个包含了几个模块查找器的列表,默认情况下,sys.meta_path中具有如下的查找器,以及查找顺序:

[<class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>]

? ? ? ? 可以看到,第一个查找器时内置模块查找器,即python如果没有在sys.modules中找到相应模块,则会进一步查找内置模块中是否有想要被导入的模块。如果内置模块中没有找到,会进一步查找frozen模块,如果还是没有找到,则再通过PathFinder去查找。这里最后一个PathFinder实际上就是通过sys.path中的路径逐个查找的,如果还是没有找到,则最终会报出异常。

? ? ? ? sys.meta_path是一个可以改变的列表,如果我们在导入模块之前,改变这个列表的内容,都会影响python对模块的查找,比如调换顺序则会影响python对模块的查找顺序,或者直接清空该列表,那么python除了sys.modules缓存的模块外,不能成功导入任何模块。

? ? ? ? 内置模块指的是用c编写的关键组件模块,可以通过sys.builtin_module_names查看有哪些内置模块;frozen模块则是用python编写,但是通过python的freeze工具编译后同python解释器一同发布的模块,这种模块可以直接再unix系统上运行,就跟c的二进制程序一样。

? ? ? ? 如果我们想知道某个模块的详细信息,可以通过importlib.util.find_spec(m)函数获取模块m的信息,可以查看其到底时什么模块。

sys.path

? ? ? ? 可以看到,在进入sys.path中的路径查找之前,python对于模块查找会先经历sys.modules缓存查找、内置模块查找和frozen模块查找三个环节,只有上面三个都没有找到,才会进入sys.path路径查找。

? ? ? ? sys.path中主要依次包含三类路径:直接主脚本所在的目录或者进行交互python环境所在的工作目录、PYTHONPATH路径和包默认的安装路径(如site-package)。

相对导入

? ? ? ? 除了绝对导入外,python中还可以进行包内的相对导入,用点号开头表示,比如from . import xxx、from .. import xxx、from .A import xxx、from ..A import xxx等都是相对导入,相对导入有两个语法特点:1、 一定时以from开头导入;2、from后跟的名称一定是以点号开头,表示相对路径。

? ? ? ? 相对导入是通过当前模块的名称__name__来定位被导入模块位置的。假设包A的结构如下所示,在test.py中有from .. import t0,t1的__name__属性为A.B.t1,一个点号表示A.B,两个点号表示A,python会通过t1的__name__属性来定位其所在的位置,以及查找被导入模块的位置。

A/
  __init__.py
  t0.py
  B/
    __init__.py
    test.py
    t1.py

? ? ? ? 那么,当执行from .. import t0时,python背后到底做了什么?首先,跟绝对导入一样,python会在模块缓存sys.modules中查找是否已经有A,如果没有,则会先导入A,进一步检查是否有A.t0,如果有就直接引用,如果没有,python会先从A的命名空间中查找,A的命名空间就是A下面的__init__.py脚本执行后,里面所创建的对象,如果没有在A的命名空间中找到,则会在A对应目录下查找,如果还是没有找到,则会报出异常。所以,对于相对导入,在真正查找到物理模块前,会先经历sys.modules缓存模块查找和包模块的初始化文件创建的命名空间查找。

__init__.py相对导入

? ? ? ? __init__.py初始化文件中的相对导入和常规相对导入是一样的,这里之所以特地拿出来强调,是因为在目录查找之前,还会经历__init__.py的命名空间查找,所以如果所在相应的包目录下并不存在想要被导入的模块,但是在__init__.py中定义了相应的被导入对象的话,那么导入语句依然会成功运行,会导入__init__.py中定义的对象。

mian脚本中的相对导入

? ? ? ? 通常相对导入语法只会在包内发生,但是有一个特例,那就是在__name__属性为__main__的主脚本中也允许相对导入语法。当在主脚本中运行相对导入时,主脚本就相当于包的顶层目录下的__init__.py,只允许一个点号,即from . import x,因为如果超过一个点号就会报超出顶层包目录的异常,而且,这里的x也只有在主脚本里面在导入语句之前被定义的情况下,该相对导入语句才会成功运行。

Reference

1.?5. The import system — Python 3.10.4 documentation ? ??

2.?Python Cookbook, Third Edition: Beazley, David, Jones, Brian

3.?PEP 328 – Imports: Multi-Line and Absolute/Relative | peps.python.org

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:14:27  更:2022-05-05 11:15:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:58:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码