15_Python的模块module
1.模块的概述
1.模块是Python程序架构的一个核心概念,每一个以.py结尾的Python源代码文件都是一个模块
2.模块名和标识符的命名规则一样,由数字字母下划线组成且不能以数字开头,也不要和系统的模块文件重名
3.在模块中定义的全局变量,函数,类都是供外界直接使用的工具,模块是一个包含有一系列变量函数类等组成的程序组
4.模块就好比工具包,要想使用这个工具包中的工具就需要先导入模块,一般模块名都是以小写字母开头
5.Python中每个模块都有一个内置属性__file__可以查看模块的完整路径
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pygame print(pygame.__file__) # '/usr/local/lib/python3.7/site-packages/pygame/__init__.py'
6.__name__属性概述:
1.__name__属性可以做到测试模块的代码只在测试情况下被运行,而在被导入时不会被执行
2.__name__是Python的一个内置属性记录着一个字符串,如果被其他文件导入__name__记录的就是模块名反之则是__main__
3.用来判断当前模块是否为主模块
1.当此模块作为主模块(也就是第一个运行的模块)运行时,__name__属性绑定'__main__'
2.当此模块不是主模块时模块为文件名去掉'.py'
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# modules_test1.py文件作为主模块执行时 import sys # 如果被其他文件导入__name__记录的就是模块名反之则是__main__ print(__name__) # __main__ # __main__记录当前执行文件所在的地址 print(sys.modules['__main__']) # <module '__main__' from '/Users/modules_test1.py'> # sys.modules[__name__]写在那个文件里就代表那个文件的命名空间 print(sys.modules[__name__]) # <module '__main__' from '/Users/modules_test1.py'> # modules_test1.py文件作为被modules_test2.py文件导入模块执行时 import sys import modules_test1 # 如果被其他文件导入__name__记录的就是模块名反之则是__main__ print(__name__) # __main__ # __main__记录当前执行文件所在的地址 print(sys.modules['__main__']) # <module '__main__' from '/Users/modules_test2.py'> # sys.modules[__name__]写在那个文件里就代表那个文件的命名空间 print(sys.modules[__name__]) # <module '__main__' from '/Users/modules_test2.py'> """模块加载结果 modules_test1 # 此时__name__属性记录着模块名 <module '__main__' from '/Users/modules_test2.py'> <module 'modules_test1' from '/modules_test1.py'> """
2.模块的(作用, 分类, 索引顺序, 加载过程)
1.模块的作用:
1.让一些相关的变量函数类等有逻辑的组织在一起使逻辑结构更加清晰,模块中的变量函数和类可以供给其他模块使用
2.模块化编程有利于多人合作开发和解决函数名和变量名冲突问题,模块内的变量的作用域为模块内全局,使代码更加易于维护提高了代码的重用率
3.模块化编程思想: 高内聚,低耦合
高内聚: 使模块功能单一,不混杂
低耦合: 模块之间尽量减少相互的关联和影响
2.模块的分类:
1.内置模块: 在解释器的内部可以直接使用
2.标准库模块: 安装Python时已安装且可以直接使用
3.第三方模块: 需要自己安装才能使用
4.用户自己编写的模块: 可以作为其他人的第三方模块
3.导入模块时的路径索引顺序: 先索引程序运行时的路径,找不到时索引 sys.path 里提供的路径,依然找不到时再次索引内置模块
4.模块的加载过程:
1.在模块导入时模块内的所有语句都会被执行
1.先索引相关路径找到模块的.py文件,判断是否有此模块对应的.pyc文件,如果没有此文件则用.py文件生成相应的.pyc文件在进行加载
2.如果.pyc文件已经存在则判断.pyc文件和.py文件的修改时间再决定是否从新生成.pyc文件
2.如果一个模块已经导入,则再次导入时不会重新执行模块内的语句
3.模块的重新加载方法:
import imp
imp.reload(mymod) # 重新加载已经加载过的mymod模块
5.模块导入添加path路径示例
import sys import os # lst = __file__.split('/') # # base_path = '/'.join(lst[:-2]) base_path = os.path.dirname(os.path.dirname(__file__)) sys.path.append(base_path) from core import main
3.模块的导入语法
1.导入模块时,每个模块独占一行,且导入模块应该放到代码的顶部
2.用as给模块起别名时应该遵循大驼峰命名法;导入之后可以通过模块.使用模块提供的工具全部变量,函数,类等
3.导入多个模块时出现同名的工具,后倒入的模块会覆盖先导入的模块的同名工具,可以通过起别名来解决同名问题
4.导入模块顺序时应遵循PEP8的代码规范: 内置模块 标准库模块 第三方模块 自己写的模块
5.关于 'import' 导入和 'from 模块名 import 工具名' 导入的区别
import 导入实际上是吧模块中的所有代码放到当前写导入语句的位置
from 模块名 import 工具名 导入实际上是在当前写导入语句位置创建一个和工具名同名的变量指向被导入模块对应的工具名
import 模块名
import 模块名 as 别名
from 模块名 import * # 从模块中导入所用的工具,不推荐使用,工具重名是不会有任何提示
from 模块名 import 工具名
from 模块名 import 工具名 as 别名
4.模块的编译compile
编译 解释执行
mymod.py --->> mymod.pyc ---> python3
5.模块的文档字符串
模块内第一行没有赋值给任何变量的字符串为文档字符串
模块的文档字符串被绑定在模块的 __doc__属性上,可以用help函数查看
6.模块的 __all__列表与模块的影藏属性
模块中的__all__列表是一个用来存放可导入属性的字符串列表;当用from import * 语句导入模块时,只导入 __all__ 列表内的属性
模块中以_开头的属性,在from import * 语句导入时,将不会导入,通常称这些属性为隐藏属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 此py文件被作为模块导入时只能导入login方法 __all__ = ['login'] name = 'alex' def login(): print('login',name) import sys my_module = sys.modules[__name__] getattr(my_module,'login')()
7.模块的发布,安装与删除
1.创建setup.py文件
form distutils.core import setup setup( name="msg", # 包名 version="1.0", # 版本 description="发生和接收消息模块", # 描述信息 long_description="完整的发送和接收消息模块", # 完整的描述信息 author="作者", # 作者 author_email="xxx@xxx.com", # 作者邮箱 url="www.xxx.com", # 主页 py_modules=[ "msg.send_msg", "msg.recv_msg" ] )
2.用终端构建模块
python3 setup.py build
用终端发布压缩包
python3 setup.py sdist
3.安装模块
tar -zxvf 模块压缩包
sudo python setup.py install
4.删除模块: 用import导入模块,用模块.__file__内置函数找到模块所在路径,删除路径下的模块文件
8.模块化开发流程和导入踩坑点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from recv_msg import * from handle_msg import * def main(): # 1. 接收数据 recv_msg() # 2. 测试是否接收完毕 test_recv_data() # 3. 判断如果处理完成,则接收其它数据 recv_msg_next() # 4. 处理数据 handle_data() # 5. 测试是否处理完毕 test_handle_data() # 6. 判断如果处理完成,则接收其它数据 recv_msg_next() if __name__ == "__main__": main()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from common import RECV_DATA_LIST # from common import HANDLE_FLAG import common def recv_msg(): """模拟接收到数据,然后添加到common模块中的列表中""" print("--->recv_msg") for i in range(5): RECV_DATA_LIST.append(i) def test_recv_data(): """测试接收到的数据""" print("--->test_recv_data") print(RECV_DATA_LIST) def recv_msg_next(): """已经处理完成后,再接收另外的其他数据""" print("--->recv_msg_next") # if HANDLE_FLAG: if common.HANDLE_FLAG: print("------发现之前的数据已经处理完成,这里进行接收其他的数据(模拟过程...)----") else: print("------发现之前的数据未处理完,等待中....------")
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from common import RECV_DATA_LIST # from common import HANDLE_FLAG import common def handle_data(): """模拟处理recv_msg模块接收的数据""" print("--->handle_data") for i in RECV_DATA_LIST: print(i) # 既然处理完成了,那么将变量HANDLE_FLAG设置为True,意味着处理完成 # global HANDLE_FLAG # HANDLE_FLAG = True common.HANDLE_FLAG = True def test_handle_data(): """测试处理是否完成,变量是否设置为True""" print("--->test_handle_data") # if HANDLE_FLAG: if common.HANDLE_FLAG: print("=====已经处理完成====") else: print("=====未处理完成====")
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
RECV_DATA_LIST = list() # 用来存储数据 HANDLE_FLAG = False # 用来标记是否已经处理完成
版权:本文版权归作者
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任