模块、包的定义

模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:模块的本质是为了实现一个功能),本质就是.py结尾的python文件 (文件名:test.py,对应的模块名:test)

包:用来打包多个模块(.py文件),本质就是一个目录(必须有__init__.py文件),如果想要导入一个包就是解释(执行)这个包下的__init__.py文件。

导入方法

导入模块:

import module_name   (导入所有)

指定导入:from module_name import * (导入所有);   

导入指定方法:from module_name import abc  

导入模块中的多个方法: from module_name import abc123,abc456

导入模块中的方法:import module_name.abc

导入模块中的变量:import module_name.name

导入多个模块:import module1_name, module2_name

导入后别名: from module1_name import logger as abc123 使用该方式导入的话,需要通过别名来调用,如abc123()

不建议通过from方式来调用函数,假如当前.py文件中有一个叫abc的方法函数,然后我们如果通过使用from module_name import *来调用的话那么,且调用过来的module_name模块中也有个叫abc的方法函数,那么在当前.py文件中来调用abc()函数时就会导致冲突。

如果使用import module_name就不同了,需要使用module_name.abc的方式才可以调用module_name模块的方法函数,即使当前.py文件中有同名的也不会冲突。

import本质

Python22 模块详解 之 import本质_第1张图片

我们在test.py中import time这个模块,其本质意义就是将time模块中的代码解释一遍(运行一遍)然后赋值给一个变量,这个变量就是time

from time import strftime相当于将time模块中的strftime方法给解释了一遍然后放入test.py文件中。

通过from time import strftime方式相当于打开了time模块这个文件然后将strftime给导入到当前所在的test.py文件中,所以在调用的时候直接strftime就可以了

通过直接import time方式后,相当于将time中的代码赋值给了time,所以在当前test.py中调用的时候需要time.strftime才可以调用。

Python22 模块详解 之 import本质_第2张图片
需要time.xxx才可以调用
Python22 模块详解 之 import本质_第3张图片
直接调用即可

导入模块的本质:就是把python文件解释一遍。

导入包的本质:就是执行包下的init.py文件。

动态路径

1、方法(一)

Python22 模块详解 之 import本质_第4张图片
在新建的包中的init.py写一个print代码

Python22 模块详解 之 import本质_第5张图片
test.py与q1这个包在同级目录,所以调用q1是没问题的,可以看到图中下面的执行结果。

Python22 模块详解 之 import本质_第6张图片

Python22 模块详解 之 import本质_第7张图片
调用不同目录的模块

image_1c0bhf3591ecc3o0198cdq817io3k.png-12.3kB
可以看到无法直接调用不同目录的模块

Python22 模块详解 之 import本质_第8张图片
默认先从当前目录去找q1这个目录找,然后在去sys.path(图中圈起来的路径)这些个路径去找,找不到就会报错。
打印的sys.path路径可以看到是一个列表,在列表中没有q2这个目录的路径,所以会找不到for_test.py导致报错。

通过os模块来查看当前的绝对路径
Python22 模块详解 之 import本质_第9张图片
image_1c0bhgqbb1ln852c1eu7pc5c6f4r.png-3.2kB
显示绝对路径,可以看到packet.py

print (os.path.dirname(os.path.abspath(__file__)))    

通过os.path.dirname获取(os.path.abspath(file)的目录
image_1c0bhht561e2ma8kkae159usbg58.png-2.7kB
目前只获取到了q1这个目录,在这个目录下找不到for_test模块

print (os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

多一个os.path.dirname来获取更上一级的目录
image_1c0bhj3nfl8pumqv8k17mi1j545l.png-2.6kB

Python22 模块详解 之 import本质_第10张图片
新建一个与q1同级的mian模块

Python22 模块详解 之 import本质_第11张图片
之前讲过sys.path是列表形式,所以需要将动态新生成的路径加入到sys.path中

image_1c0bhn80a18vf1rvhsokso9s76s.png-14.8kB
通过Import main然后在调用,可以看到执行结果

#### 2.方法(二)
Python22 模块详解 之 import本质_第12张图片
通过同样的方式去调用for_test就出现问题了,这是因为for_test在q2这个目录中,不能直接使用import来导入

Python22 模块详解 之 import本质_第13张图片
需要通过from q2这个目录然后在import,也就是从q2这个包中导入模块。

3.方法(三)

image_1c0bhpljhj6n1m50c2h9361msc83.png-13.9kB
之前了解过import包就相当于import这个包下的init模块

Python22 模块详解 之 import本质_第14张图片
执行没有问题

Python22 模块详解 之 import本质_第15张图片
在这个init模块下我们使用from . import for_test,也就是说在packet.py中去import q2就相当于调用了init.py,然后init又调用了for_test.py,所以上图中可以通过q2.for_test.login()来调用。

from 后面的那个符号 点 表示从init的当前目录(q2这个包目录)去import

导入优化

Python22 模块详解 之 import本质_第16张图片
定义aa模块

Python22 模块详解 之 import本质_第17张图片
在bb.py中import aa,然后在bb.py中定义函数并调用aa模块中的方法(函数),不过这样调用的话,在bb.py中的每一个函数都需要先去找aa模块,然后再去找test()这个方法,被调用一次就需要找一次,如果调用次数多的话,就需要大量的重复性工作,这样运行程序相对会比较慢。

Python22 模块详解 之 import本质_第18张图片
使用from方法来导入,相当于把这个test()导入到bb.py文件中了,这样在调用test()这个函数的时候,直接就是从本程序中直接调用,相比上一种方式运行速度会快。