六、模块和包
一、模块
1、基础
每个文件都是 一个模块,并且模块导入其他模块后就可以使用导入模块定义的变量名。模块可以由两个语句和一个内置函数处理:
- import:使导入者以一个整体获取一个模块;
- from:允许导入者从一个模块文件中获取特定的变量名;
- imp.reload:在不终止Python程序的情况下,提供一种重新载入模块文件代码的方法。
2、使用模块的好处
- 代码重用;
- 系统命名空间的划分;模块是Python中最高级别的程序组织单元。
- 实现共享服务和数据。
3、import工作原理
Python中,导入并非只是把一个文件文本插入另一个文件而已。导入是运行时的运算,程序第一次导入指定文件时,会执行三个步骤:
- 搜索(找到)模块文件;
- 编译成位码(需要时【可选】);
- 执行模块的代码来创建其所定义的对象。
在之后导入相同模块时,会跳过这三个步骤,而只提取内存中已加载的模块对象:技术上,Python把载入的模块存储到 一个名为sys.modules的表中,并在一次导入操作的开始检查该表;如果模块不存在,将会启动一个三个步骤的过程。
4、模块搜索路径
- 程序的主目录;
- PYTHONPATH目录;
- 标准链接库目录;
- 任何.pth文件的内容(如果存在),用户把有效的目录添加到模块搜索路径中,就是在后缀名.pth(路径)的文本文件中一行行地列出目录。
这四个组件组合成sys.path。
二、包
1、基础
导入也可以指定目录路径。Python代码的目录称为包,这类导入称为包导入。包导入是把计算机上的目录变成另一个Python命名空间。导入基础,在导入时将文件名改为路径名,之间使用点号相隔(点号对应于机器上目录层次的路径):
- import dir1.dir2.mod
- from dir1.dir2.mod import x
2、包和搜索路径
模块搜索路径上的项目提供了平台特定的目录路径前缀
- __init__.py 包文件
- 选择包导入,则包导入语句的路径中的每个目录都必须有__init__.py文件,否则导入包会失败。
- 可包含代码也可为空,更像一种声明,可以防止有相同名称的目录隐藏在模块搜索路径中
- 扮演包初始化的钩子、替目录产生模块命名空间及使用目录导入时实现from *(即from .. import * )行为的角色:
- 包初始化,Python首次导入某个目录时,会自动执行该目录下__init__.py文件中的所有代码;
- 模块命名空间的初始化,在包导入的模型中,脚本内的目录路径,在导入后会变成真实的嵌套对象路径。
- from * 语句的行为,可以在__init__.py中使用__all__列表定义目录以from * 语句形式导入时,需要导出什么
3、相对和绝对导入
- 相对导入:使用点号,只在包的内部搜索,且不会搜索位于导入搜索路径(sys.path)上某处的同名模块
- 不带点号的import语句总是会引发Python略过模块导入搜索路径的相对部分,且在sys.path所包含的绝对目录中查找。其作用域:
- 相对导入适用于只在包内导入;
- 相对导入只是用于from语句;
- 数据含糊不清。
- 不带点号的import语句总是会引发Python略过模块导入搜索路径的相对部分,且在sys.path所包含的绝对目录中查找。其作用域:
4、文件夹被视作包需满足两个条件:
(1)文件夹中必须有__init__.py文件;
(2)不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。