python--5、模块

模块

程序的代码根据作用分散写入多个文件,这些文件相互引用,以实现程序的功能,这些文件即称之为”模块“。
自己定义的函数或者变量为了防止在解释器中执行完退出后丢失,需要把代码写到文件中,再直接执行,称为“脚本”。
但是程序在功能越来越多后,为了便于管理代码,通常将一个程序分为多个文件,这样使得程序结构更加清晰,也方便管理。这样就可以吧他们当做模块来导入到其他的模块中。实现了功能复用。
同理,我们也可以拿来别人写好的模块来导入到自己的项目中使用,以提升开发效率。

一个模块即包含Python定义和声明的文件,模块一般用于导入使用。

import 可以加载的模块有:

  • Python编写的.py文件
  • 已被变异为共享库或DLL的C或C++扩展
  • 吧一系列模块组织到一起的文件夹(包的概念在之后介绍)
  • 使用C编写并链接到Python解释器的内置模块。

示例:

#test.py
print('this is test')
number = 123
def ins1():
    print('test模块',number)
def ins2():
    print('test模块')
    ins1()
def ins3():
    global number
    number = 0

import

模块可以包含可执行的语句和函数的定义,为了初始化模块。他们在模块第一次被import导入时执行(即使在同一模块在一个程序中import了很多次,只有第一次导入时将模块加载到内存,后续的import只会引用)

注:我们可以从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。

import导入过程

为相应模块创建新的名称空间, 在新创建的命名空间中执行模块中包含的代码,创建模块名来引用该名称空间。

  • 在整个导入模块时,被导入模块有独立的名称空间

被导入的每个模块都是一个独立的名称空间,定义在模块中的函数把这个模块当作全局名称空间,可防止模块的全局变量与调用它的文件的全局变量冲突。

  • 为模块起别名
import test as tt
print(tt.money)

例如两个相似的模块有两个的功能一样的方法。根据用户输入判定该是哪个模块,再给这个模块起成特定的别名。

  • 在一行导入多个模块
import module1,module2,……

from module_name import func

与import的对比

  • from .. import ..,是将模块中的方法名字直接导入到当前的名称空间中,so,在当前文件名称空间中,直接使用名字即可。
    若导入的模块方法中还需回掉原来模块的别的方法or变量,则还是以原模块中的为准。
    若是导入的模块方法直接与现文件中的方法冲突,则导入进来的会被覆盖掉。
  • 也支持as,对导入的方法做别名。
  • 也支持","导入多个

from .. import *

把模块中非"_"下划线开头的名字都导入到当前位置。
这个可以使用__all__来控制*导入的方法。
#__all__=['money','read1'] #这样在另外一个文件中用from spam import *就这能导入列表中规定的两个名字

模块的重载(不重要)

模块被导入后,被放到sys.module的字典中。若改变了模块内容,必须重启程序。python不支持重新加载或卸载之前导入的模块。
哪怕在sys.module中删了模块对象,但仍有可能被其他程序组件引用。不会清掉。
尤其是引用了这个模块中的一个类,用这个类产生了很多对象,因而这些对象都有关于这个模块的引用。

两种python文件

  • 脚本:一个文件就是整个程序,用于被执行。
  • 模块:文件中存放着一堆功能,用于被导入使用。

python内置的全局变量__name__

  • 当文件被当作脚本执行时:__name__ 等于 '__main__'
  • 当文件被当作模块导入时:__name__等于模块名

用于控制.py文件在不同的应用场景下执行不同的逻辑。

模块的搜索路径

内存中已经加载的模块 -> 内置模块 -> sys.path路径中包含的模块。
#我们自定义的模块名不应该与系统内置模块重名。

可以通过修改sys.path来添加环境变量。

import sys
sys.path.append('/a/b/c')
sys.path.insert(0,'/x/y/z')

搜索环境变量时会在sys.path中从左往右找,sys.path中还可以包含.zip文件和.egg文件,python会把.zip文件当作一个目录取处理。

#.egg文件是由setuptools创建的包,这是按照第三方python库和扩展时使用的一种常见格式,.egg文件实际上只是添加了额外元数据(如版本号,依赖项等)的.zip文件。

#要强调的:只能从.zip文件中导入.py,.pyc等文件。使用C编写的共享库和扩展块无法直接从.zip文件中加载(此时setuptools等打包系统有时能提供一种规避方法),且从.zip中加载文件不会创建.pyc或者.pyo文件,因此一定要事先创建他们,来避免加载模块是性能下降。

编译Python文件

为了提高“加载模块的速度”,Python解释器会在__pycache__目录中缓存每个模块编译后版本,格式:module.version.pyc。保证了编译后的结果可多版本共存。
#python检查源文件的修改时间与编译的版本进行对比,如果过期就需要重新编译,这是自动的过程。且编译的模块是平台独立的。所以相同的库可以在不同架构的系统之间共享,即pyc是一种跨平台的字节码,类似于JAVA .net。是由python虚拟机来执行的,但是pyc的内容跟python的版本相关,不同的版本编译后的pyc文件不同,2.5编译的Pyc文件不能到3.5上执行,并且pyc文件是可以反编译的。因而它的出现仅仅是用来提升模板的加载速度的,而不是用来加密

python解释器在以下两种情况下不检测缓存

#1 如果是在命令行中被直接导入模块,则按照这种方式,每次导入都会重新编译,并且不会存储编译后的结果(python3.3以前的版本应该是这样)
python -m spam.py

#2 如果源文件不存在,那么缓存的结果也不会被使用,如果想在没有源文件的情况下来使用编译后的结果,则编译后的结果必须在源目录下
#注:

    • 模块名区分大小写,foo.py与FOO.py代表的是两个模块
    • 只有使用import语句是才将文件自动编译为.pyc文件,在命令行或标准输入中指定运行脚本则不会生成这类文件,因而我们可以使用compieall模块为一个目录中的所有模块创建.pyc文件
原文地址:https://www.cnblogs.com/jinyudong/p/7703597.html