1.什么是包
包本质上就是一大堆模块的集合,把解决一类问题的所有模块都放在一个文件夹里,这个文件夹就可称为一个包。
在python中,使用 包名.模块名来调用包中的具体模块,需要注意的有以下几点:
- 无论是以 import 形式还是 from … import 形式导入,在导入语句中含有 . 的
需要注意,这是有关包的导入方式; - 包的本质就是一个文件夹,文件夹中都是解决一个具体问题的 py 文件,需要注意的是,在python2中,一个包中必须含有 __init__.py文件,若没有此文件导入包时会报错;但是在python3中,此文件不存在也可以,但是代码会出现一点缺陷;
- import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,此文件在当包被导入时会自动执行,导入包本质就是在导入该文件。
创建如下目录结构以及内容:
2.包的导入 - import
在与 glance 目录同级的py文件中进行导入:若我们想使用 policy.py 中的 get 方法,使用 import 导入与调用方式如下:
注意:当我们导入一个包时,不管使用 import 还是 from … import 其中导入语句的 . 左边一定要是一个包.
import glance.api.policy
glance.api.policy.get()
运行结果如下:
当然也支持导入时进行重命名:
import glance.api.policy as policy # 与上面等价
policy.get()
运行结果都是一样的,掉用的都是同一个函数:
3.包的导入 - from … import
注意:当我们使用此种方式导入时,import 的右边必须是一个变量,即不能是 from c import a.b 的形式
使用 from … import 导入与调用如下:
from glance.cmd import manage
manage.main()
运行结果如下:
4.__init__.py 文件
当我们导入一个包时 (无论以何种方式导入),__init__文件中的代码都会被执行,此文件可以为空,也可以写一些初始化的代码;
在python2中,包中必需要含有此文件,否则导入时报错;python3中,可以不含有此文件,运行时不会报错;
例如,我们在glance/__init__.py 文件中添加如下代码:在glance同级的py文件中只导入glance包,再执行:
import glance
运行结果如下:
__init__.py文件的应用:
由于在此文件中的代码在导入包时会被执行,所以对于 glance 目录下的所有包,都可以在 __init__.py文件 中进行导入,这样我们只需要导入 glance 就导入了所有的模块:
5.from … import *
我们已经知道,当我们导入一个模块时使用 * 导入,那么就会导入对应模块中 __all__ 中的变量名字,__all__ 中不存在的变量名字我们是无法调用的;
那么当我们在导入一个包时使用 * 参数,则会导入这个包中 __init__文件中__all__ 中含有的模块名称,__all__ 参数中不含有的模块名字,即使此模块存在,我们无法使用;
例如:api/__init__.py文件的__all__参数只含有policy模块的名字,
当我们在调用时,可以使用如下方式进行调用:
from glance.api import *
policy.get()
# versions.create_resource() # 此时 versions 模块是不能使用的
运行结果如下: