python-模块和包
模块的分类
内置模块
- 安装python解释器的时候跟着装上的那些方法
第三方模块/扩展模块
- 没在安装python解释器的时候安装的那些功能
自定义模块
- 你写的功能如果是一个通用的功能,那你就把它当做一个模块
什么是模块
- 有的功能开发者自己无法完成,这样的话需要借助已经实现的函数\类来完成这些功能
- 你实现不了的功能都由别人替你实现了
- 操作系统打交道,和时间打交道, 和网络通信等等
- 别人写好的一组功能 文件夹/py文件/C语言编译好的一些编译文件
为什么要有模块?
- 分类 管理方法
- 节省内存
- 提供更多的功能
如何使用模块?
import
一个py文件就可以作为一个模块
模块的导入:直接导入文件的名字,不需要带着后缀
模块中的函数调用:模块名.函数名()
模块的名字必须要满足变量的命名规范,一般情况下 模块都是小写字母开头的名字
导入模块的时候做了三件事:1.首先开辟了一个新的命名空间my_moudle
2.执行了my_moudle内的代码
3.将my_moudle里面的名字和命名空间绑定在一起了
import my_module # def login():print('in mine login') # name = '太亮' # login() # my_module.login() # # print(my_module.name
模块的重命名
# import my_module as m # m.login() # my_module.login()
导入多个模块
PEP8规范
- 所有的模块导入都应该尽量放在这个文件的开头
- 模块的导入也是有顺序的
- 先导入内置模块
- 再导入第三方模块
- 最后导入自定义模块
import os
import my_module
import re,json,random # 一行导入多个模块
from ...import...
import my_module from my_module import login # 重命名 # from my_module import login as l # l() # 导入多个 # from my_module import login,name # login() # print(name) # name = '太亮' # login() # 导入多个之后再重命名 # from my_module import login as l,name as n # from 模块 import * # from my_module import * # login() # name
把模块当成脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'
当做模块导入:
__name__= 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
# 运行一个py文件的两种方式 # 1.以模块的形式运行 # import my_module # if __name__ == '__main__': # my_module.login() # 2.直接pycharm运行 cmd运行 # ----以脚本的形式运行 # 那么需要在本文件中直接打印的代码上加上 # if __name__ == '__main__': # 在编写py文件的时候 # 所有不在函数和类中封装的内容都应该写在 # if __name__ == '__main__':下面 # import sys # import my_module # sys.modules # {'sys':文件的内存地址, # 'my_module': my_module的地址 # '__main__':当前直接执行文件所在的地址} # 存储了所有导入的文件的名字和这个文件的内存地址 # 再使用反射自己模块中的内容的时候 # import sys # getattr(sys.modules[__name__],变量名)
模块搜索路径
python解释器在启动时会自动加载一些模块,可以使用sys.modules查看
在第一次导入某个模块时(比如my_module),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找my_module.py文件。
模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
千万不要自己定义这些你熟悉的模块或关键字啊啥的作为自己的模块名
import sys print(sys.path) sys.path.append('D:\sylar\python_workspace') import aaa # 模块没导入之前在哪儿? # 在硬盘上 # 安装python # python整个包的结构不变 # 它会记录一个安装目录 # 其他所有目录都是根据安装目录来写死的 # 'D:\\sylar\\python_workspace\\day22', 是你当前运行的脚本所在的目录 # 'D:\\sylar\\python_workspace\\day22' 是pycharm在你打开项目的时候给你添加进来的项目根目录 # 剩余所有都是python内置的目录 # 内置模块的导入 # 第三方模块的导入 # 内置模块的导入和第三方模块的导入都不需要你操心了 # 自定义的模块能否被导入 # 看sys.path当中 是否存在你要导入的文件 所在的目录 # 总结 # 模块的搜索路径全部存储在sys.path列表中 # 导入模块的顺序,是从前到后找到一个符合条件的模块就立即停止不再向后寻找 # 如果要导入的模块和当前执行的文件同级 # 直接导入即可 # 如果要导入的模块和当前执行的文件不同级 # 需要把要导入模块的绝对路径添加到sys.path列表中
包
包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
# import glance.api.policy # glance.api.policy.get() # import glance.api.policy as policy # policy.get() # from glance.api import policy # policy.get() # 导入包 相当于执行了这个包下面的__init__.py # import glance # # 设计一下init文件来完成一些模块的导入 # glance.api.policy.get() # glance.db.models # from aaa import glance from aaa import glance2 glance2.api.policy.get()
绝对导入和相对导入
我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:
绝对导入:以glance作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
在glance/api/version.py #绝对导入 from glance.cmd import manage manage.main() #相对导入 from ..cmd import manage manage.main()