2.4 - 模块 & 包
2.4.1 模块以及模块导入
一个python文件可以看作是一个模块,文件名( 不含后缀 )即 模块名。
采用不同的模块,可以避免模块内方法的命名冲突。
一个程序只会将模块导入一次;程序将模块导入时会执行该模块。
import module1, module2 # 只是导入模块,需要通过 module_name.method_name的方式来调用方法 import module1 as alias1, module2 as alias2 from module1 import item1 # 相当于在本模块中直接定义了该方法,可以直接使用 from module1 import item1 as alias3, item2 as alias4 # 导入random的第一种方式 import random random.randint(0,5) # 导入random的第二种方式 from random imort randint randint(0,5)
注:1.慎用 from module import * , 很容易出现名称重复的情况。
2. import module 之后,只是将整个模块导入了,如果想要使用模块中的某个方法,需要通过 模块名.方法名 的方式来调用。可以这样理解:在模块A中import模块B,只是扩大了模块B的可使用范围到模块A,进而模块A可以通过 模块名B.方法名 的方式来调用后者,本质上两个模块还是独立的。
2.4.2 包以及包导入
Python包实际上就是一个文件夹,但是这个文件夹必须包含 __init__.py 模块,该模块用来定义 导入包之前的初始化操作。
包可以避免模块命名冲突;并且在大型项目中,可以将不同类型的模块放在不同的包中,方便进行模块管理。
import package1 import package1 as alias1 from package1 import module1 as alias2, module2 as alias3 from package1.module1 import item1 as alias4, item2 as alias5
2.4.3 模块导入的 搜索路径&优先级
import sys print(sys.path) # 列表中即:同名模块导入的优先级顺序,高 =》低
通过 sys.path 可以查看模块导入路径的优先级顺序:
最优先 模块的同级目录;其次 项目根目录(直接在项目根目录下,不能是根目录下的某个包下);最后当前虚拟环境下的包目录。
如果,被导入的模块既不在本模块的同级目录,也不在本项目的根目录下,而是在项目根目录的某个包目录下,导入的时候需要:from package.module import item
注:
在大型python项目中,模块和包的__init__模块 在导入其它模块的时候,最好 一律从项目的根路径开始导入,因为在多层级的项目结构中,如果一个模块X导入了一个包P,而包P的 __init__中又导入了同级目录下的模块Y,在这样的连锁导入中,如果__init__模块不是从项目根目录导入模块Y而是直接【 import Y】,虽然在模块__init__中是可以正常运行的,但是在模块X中运行的时候会报错,因为:模块X导入包P,自动触发__init__模块,该模块中会导入包P下的 Y,但是 对于模块X而言,模块X 既不在它自己的同级目录,也不在项目根目录的直接子目录下,因此会报错!!!
由此可见:所谓的 “导入模块的时候会执行该模块”,作用机理 就相当于 将被导入模块的代码放在 import 语句的位置执行一遍,并为其开辟一个单独的命名空间(有模块导入的前提下)。仅此而已。
2.4.4 __name__ 属性
__name__是一个模块的固有属性,其显示了模块是在本模块内部被使用,还是在其它模块中被使用。当在本模块内部被使用的时候,__name__ 属性的值为 "__main__",当该模块被其它模块导入使用的时候,__name__ 属性的值为 该模块的模块名。
import module1 as m1 print(__name__) # 本模块的__name__属性:__main__ pinrt(m1.__name__) # 本模块中其它模块的 __name__ 属性:模块名
该特性适用于:模块的功能测试等 只需要在本模块内运行而不需要被导入其它模块使用 的场景。