python中的模块概念以及包、库的概念
模块的基本概念:
,它就是一个扩展名为.py的python程序。因此对于一个.py的python文件而言,既可以把它当作程序来执行,也可以将它作为模块引入。
导入一个模块时,python解释器会先自动在当前路径下搜索要导入的模块,如果没有找到,则会自动到python标准模块安装路径(python默认自带的)中搜索,如果还没找到,则报错ModuleNotFoundError。
在sys模块的path属性中,可以看到python自动导入的所有路径(以列表的形式存放)。sys的path属性中除了本来就有的python系统自带的标准模块的路径之外,还会将当前执行文件的路径临时的加到path属性中。所以,python解释器可以在当前路径中找模块,事实上跟同级路径的概念并没有关系,而是python解释器将执行文件的所在路径临时的加到了path属性中,且放在了第一个位置。
除了python可以自动寻找的路径之外,我们还可以指定路径,并将路径告诉python解释器。因此对于我们自己写的文件,要想可以作为模块被导入,有三种方法:
将模块写在当前目录中,python会直接自动找到;
将模块发布并安装到python标准模块安装的路径中,python也可以自动找到;
将我们自己写的模块路径append到sys模块的path属性列表中,即告诉python解释器,我们自定义的模块的路径位置。
执行了.py文件后,会发现目录中多了一个__pycache__的目录,这个目录中存放着执行.py文件后生成的文件中的import导入的模块的编译文件,下次再执行该文件时,遇到import导入的相同模块时,将直接执行此编译文件,不再重新编译相同的模块,节省执行时间。
__all__在模块中的作用:
当使用“ from 模块名 import * ”的方式从模块中导入所有内容时,模块中以_或着__开头的私有属性、函数或者类将不会被导入,因为以这种方式导入模块中的内容时,导入的将是模块中__all__属性中的内容。在默认情况下,私有属性、函数或者类是不会被放到__all__属性中的。当然我们可以自定义模块的__all__属性中的内容,让模块中的哪些属性、函数或者类(包括私有的)可以被导入。
如果是通过“ import 模块名 ”的方式导入模块,则可以用“ 模块名. ”的方式来访问模块中的所有属性、函数和类(包括私有的)。因为只有通过“ from 模块名 import * ”的方式才会导入模块中__all__中的内容。
模块中还有一个__file__属性,它可以告诉我们此模块的位置(路径)。
当一个.py文件作为模块被导入时,实际上会执行一次该文件。我们导入模块时,只是想要模块中的类、函数或者变量等,而并不是要真正的去执行该文件。所以在文件中,被执行的代码或者要调试的代码,应写在if __name__ == ‘__main__’:中。当文件作为模块导入时,则不会执行if __name__ == ‘__main__’中的内容;当文件作为.py文件执行或者调试时,就会执行if __name__ == ‘__main__’中的内容。因为文件作为模块导入的时候被执行时,__name__得到的是文件名路径的字符串;直接作为.py文件执行时,__name__得到的时’__main__’字符串。
包和库:
python标准库中包含多个包,每个包中又有多个模块,包即是目录(文件夹),用来存放模块。当要引用某个包中的模块时,需要在该包中放一个__init__.py文件。__init__.py可以只是一个空文件,将它放在某个目录中,就可以使得该目录中的其它.py文件能够作为模块被引用。
把这个目录当成普通目录(文件夹),而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是对应包的名字。调用包就是执行包中的__init__.py文件。