导入包
# 导入包的过程:就是执行包下面的__init__文件# import导入包时候,点左边的都必须是包# from...import...导入包时候,import后边不能有点# 例如:在glance包下的api包下引入policy.py模块# from glance.api import policy# 全部引入:# from glance.api import *# 其实*等价于__all__:from package.dir import helloprint(hello.x)# 可以用import导入内置或者第三方模块,# 但是要绝对避免使用import来导入自定义包的子模块,# 应该使用from... import ...的绝对或者相对导入,且包的相对导入只能用from的形式。import os,sysprint(__file__)print(os.path.abspath(__file__))base_path=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))print(base_path)sys.path.append(base_path)# 为了提高模块的加载速度,Python缓存编译的版本。# 每个模块在__pycache__目录的以module.version.pyc的形式命名,通常包含了python的版本号,# 如在CPython版本3.3,关于spam.py的编译版本将被缓存成__pycache__/spam.cpython-33.pyc,# 这种命名约定允许不同的版本,不同版本的Python编写模块共存。## Python检查源文件的修改时间与编译的版本进行对比,如果过期就需要重新编译。这是完全自动的过程。# 并且编译的模块是平台独立的,所以相同的库可以在不同的架构的系统之间共享,即pyc使一种跨平台的字节码,# 类似于JAVA.NET,是由python虚拟机来执行的,但是pyc的内容跟python的版本相关,不同的版本编译后的pyc文件不同,# 2.5编译的pyc文件不能到3.5上执行,并且pyc文件是可以反编译的,因而它的出现仅仅是用来提升模块的加载速度的。## 在速度上从.pyc文件中读指令来执行不会比从.py文件中读指令执行更快,只有在模块被加载时,.pyc文件才是更快的
模块与包from导入
# 我们导入模块有可能重复导入,为了防止你重复导入,python的优化手段是:# 第一次导入后就将模块名加载到内存了,# 后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,# 不会重新执行模块内的语句。# 我们可以从sys.module中找到当前已经加载的模块,# sys.module是一个字典,内部包含模块名与模块对象的映射,# 该字典决定了导入模块时是否需要重新导入# 查看是不是已经导入了,查看内存中是否有模块:import sysprint(sys.modules)# 我这里有一个span.py 文件,里面的内容是虾面# #spam.py# print('from the spam.py')## money=1000## def read1():# print('spam->read1->money',1000)## def read2():# print('spam->read2 calling read')# read1()## def change():# global money# money=0from span import money,read1,read2# 将span中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了,但是造成了冲突print(money)print(read1())print(read2())print(__name__)if __name__=="__main__": print("文件被当作脚本执行")
模块与包import导入
import span# 导入时候,发生了什么?# 第一件事:创建名称空间,用来存放span.py中定义的名字,# 第二件事:基于刚刚创建的名称空间执行span.py文件# 第三件事:创建名字spam指向该名称空间,来引用该命名空间,span.名字对操作,都是以这个为准print(span.money)print(hasattr(span,"money"))# 反射为True
模块的搜索路径
# 我们可以通过模块的全局变量__name__来查看模块名:# 当做脚本运行:# __name__ 等于'__main__'## 当做模块导入:# __name__=## 作用:用来控制.py文件在不同的应用场景下执行不同的逻辑# if __name__ == '__main__':# 所以总结模块的查找顺序是:# 1,内存中已经加载的模块# 2,内建模块# 3,sys.path路径中包含的模块,当前路径# 某种场景下,其他路径模块导入就不行了,所以啊,我们不能把固定的结构目录放入内存和内建,只有加入sys.path# 最好不要建和内存,内建,第三方重名的文件名