模块的导入主要使用import关键字
简单来说,每一个以扩展名py结尾的Python源代码文件都是一个模块,其他的文件可以通过导入一个模块读取这个模块的内容,从本质上来说,是载入另一个文件,并读取那个文件的内容。需要注意的是在第一次的导入之后,其他的重复导入都不会再工作,甚至在另一个窗口中改变并保存了模块的源代码文件也不行。这是由于导入是一个开销很大的操作,以至于每个文件,每个程序运行不能够重复多余一次,如果实在需要在同一个会话中再次运行文件,需要调用imp标准模块中的reload函数。
下面来看一段调用并打印系统路径的简单示例:
我们按照这个步骤来:
1.建立一个工作区,并将路径添加到系统路径中
2.定义自己的模块
3.外部模块调用
1.以我的程序为例,通常我会将自己的python工作区加入系统路径,比如我在E:\coding目录下会有一个python文件夹,专门用作平时的一些小程序的编写,那么一般我会将该路径添加到系统路径中,如下:
这个方法有好处有坏处,这个方法只适合临时添加个路径,也就是说当你重新启动命令行窗口的时候路径又不在了,不信你试试,还有一个一劳永逸的方法,就是直接在环境变量中的path路径中添加进去,这样的话就不用每次都这么麻烦了。经评论提醒,还有一种方法,那就是python中的site-packages文件夹,在python安装的时候就已经将该文件夹的路径添加到系统路径中去了,我们只需要在该文件夹下新建一个*.pth文件,在文件中添加进目录就可以了
2.定义自己的模块
只是作为测试的模块,我们简单的写一个计算函数:
3.外部模块调用
从这我们可以看出,外部模块调用时,除了可以直接import python模块,然后调用文件名.函数名之外,我们还可以使用如下这种方式,
from 文件 import 函数,这样做的好处是,省去了调用时的作用域前缀,可是现在又有一个问题了,如果,我想导入的模块有好几层文件,比如我想导入 \Test\test1\test2\test3.py 中的Calculate函数,怎么办?我们再来一探究竟,(现假设你已经有E:\\Coding\\Test\\test1\\test2\\test3.py)
从中可以看出,当有好几层文件时,若直接import,则层级之间用.来表示,引用的时候必须带上所有层级文件,这样较为不方便,于是我们可以使用 import ... as ... 来简化这种表达,或者直接用到某个函数的时候from ... import ...,就可以直接使用了。
假设还是以上述为例,如果在执行函数之后发现导入模块有需要更改的地方,我们怎么解决?假设我们需要在计算结果之前加上一句提示:如下
我们刚刚导入过的模块还会继续工作么?我们来看看:
我们会发现,提示并没有打印!这个时候该怎么办呢?这个时候就要用到reload函数,在python3中位于imp包中:
关于import是如何工作的这一点,我们基本上可以将其分为3个阶段,如下:
1.找到模块文件
2.编译成位码(需要的时候)
3.执行模块的代码
需要格外注意的是,这三个步骤只会在模块第一次导入时才会执行,之后导入相同模块时,会跳过这些步骤,只是提取内存中已加载的模块对象。
关于搜索,之前有所涉及,主要是程序根据系统路径进行搜索,这之后会将源代码编译成字节码,python然后检查字节码的时间戳,如果比源代码旧,则会重新编译生成字节码.pyc,否则直接加载字节码。最后步骤是执行字节码,依次执行,也就是说,模块的第一次导入的时候,会执行模块的字节码,如下,我们添加一条打印函数:
重新打开shell编辑器,如下:
修改之后,添加一条打印语句:
这个时候我们再来reload一下看看,并且之后再导入一下:
这些结果是能够验证我们之前的说法的.