本节内容:
1、包
一、包
1、什么是包
包是⼀种通过 '.模块名'来组织python模块名称空间的⽅式.
我们创建的每个⽂件夹都可以被称之为包. 但是我们要注意, 在python2中规定. 包内必须存在__init__.py⽂件.
创建包的⽬的不是为了运⾏, ⽽是被导入使⽤. 包只是⼀种形式⽽已. 包的本质就是⼀种模块
现在python3中可以不写__init__,但是习惯性还是写,这样好.
大小顺序:一条语句 > 语句块 > 代码块(函数,类) > py文件(模块) > 包
2、为何要使⽤包?
包的本质就是⼀个⽂件夹, 那么⽂件夹唯⼀的功能就是将⽂件组织起来,
随着功能越写越多, 我们⽆法将所有功能都放在⼀个⽂件中, 于是我们使⽤模块去组织功能,
随着模块越来越多, 我们就需要⽤⽂件夹将模块⽂件组织起来, 以此来提⾼程序的结构性和可维护性
3、包的创建
包就是一个文件夹. py2中包内必须要有一个__init__.py文件, 在python3中可以省略,但是最好都保留.
__init__.py 当我们导入一个包的时候,默认执行这个包内的__init__.py
⾸先, 我们先创建⼀些包. ⽤来作为接下来的学习. 包很好创建.
只要是⼀个⽂件夹, 有__init__.py就可以.
1.创建一些包
import os
os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
l = []
l.append(open('glance/__init__.py','w'))
l.append(open('glance/api/__init__.py','w'))
l.append(open('glance/api/policy.py','w'))
l.append(open('glance/api/versions.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/__init__.py','w'))
l.append(open('glance/db/models.py','w'))
map(lambda f:f.close() ,l)
2.获得目录结构
3.为每个的文件添加一些方法
#policy.py
def get():
print('from policy.py')
#versions.py
def create_resource(conf):
print('from version.py: ',conf)
#manage.py
def main():
print('from manage.py')
#models.py
def register_models(engine):
print('from models.py: ',engine)
4、绝对导入和相对导入
上面已经创建好了一些包,接下来我们通过导入来开始用这些包,
相对导入: 相对于当前模块所在的包. 使用的时候必须在包外面启动
绝对导入: 根据包的根目录去导入内容
全部都依赖于 sys.path,主要观察sys里面的路径
1.import的导入
# 此测试在外面新建的test.py文件下
import glance.api.policy # 直接导入
glance.api.policy.get()
import glance.api.policy as ee # 也是直接导入,起个别名也可以操作,这样不太好,不能体现具体操作了什么文件
ee.get()
2.from xxx import xxx
# 此测试在外面新建的test.py文件下
# import前面可以出现 点 .xxx(点前面必须是包), 后面不可以出现 点 .xxx
from glance.api import policy
policy.get()
from glance.api.policy import get
get()
3.绝对路径
根据包的根目录去导入内容
# 在api文件夹下
from glance.api import versions # 绝对路径, 正确的在包外引用时,sys.path的路径会是在外面的 'E:\pycharm2018\cun\day025包',
versions.create_resource(1)
import versions # 错的,也是绝对路径,但是是在包内引用
4.相对路径
.当前文件夹下
..上一层文件夹
相对于当前模块所在的包. 使用的时候必须在包外面启动
# 此测试在外面新建的test.py文件下
import sys
print(sys.path) # 随动,启动文件的sys.path的第一个路径,也是他的顶级包
sys.path.insert(0,'E:pycharm2018cunday024模块,import,for xxx import xxx') # 可以增加路径,但要用绝对路径导入,
# from .. import yitian # 这样不行,引入不了,相对路径只能引入当前文件包内的(即不能超过顶级包)
import yitian
# 包的引入不能超过顶级包
5、一个大坑
我们来看⼀个⼤坑. 比如. 我们想在policy中使⽤verson中的内容.
# 在policy.py
import versions
如果我们程序的入⼝是policy.py 那此时程序是没有任何问题的.
但是如果我们在glance外⾯import了glance中的policy就会报错
原因是如果在外⾯访问policy的时候. sys.path中的路径就是外⾯.
所以根本就不能直接找到versions模块. 所以⼀定会报错:
ModuleNotFoundError: No module named 'versions'
在导包出错的时候. ⼀定要先看sys.path 看⼀下是否真的能获取到包的信息.
最后, 我们看⼀下如何单独导入⼀个包.
# 在test.py中
import glance
此时导入的glance什么都做不了. 因为在glance中的__init__.py中并没有关于⼦包的加载.
此时我们需要在__init__.py中分别取引入⼦包中的内容.
1. 使⽤绝对路径
2. 使⽤相对路径
6、包的注意事项:
-
关于包相关的导入语句也分为import和from xxx import xxx两种, 但⽆论使⽤哪种,
⽆论在什么位置, 在导入时都必须遵循⼀个原则: 凡是在导入时带点的. 点左边都必须是⼀
个包. 否则报错. 可以带⼀连串的点. 比如a.b.c -
import导入⽂件时. 产⽣名称空间中的名字来源于⽂件, import 包, 产⽣的名称空间
中的名字同样来源于⽂件, 即包下的init.py, 导入包本质就是在导入该⽂件 -
包A和包B下有同名模块也不会冲突, 如A.a和B.a来⾃两个名称空间