day025包,绝对路径和相对路径导入

本节内容:

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:\pycharm2018\cun\day024模块,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、包的注意事项:

    1.  

      关于包相关的导入语句也分为import和from xxx import xxx两种, 但⽆论使⽤哪种,
      ⽆论在什么位置, 在导入时都必须遵循⼀个原则: 凡是在导入时带点的. 点左边都必须是⼀
      个包. 否则报错. 可以带⼀连串的点. 比如a.b.c

       

    2.  

      import导入⽂件时. 产⽣名称空间中的名字来源于⽂件, import 包, 产⽣的名称空间
      中的名字同样来源于⽂件, 即包下的init.py, 导入包本质就是在导入该⽂件

       

    3.  

      包A和包B下有同名模块也不会冲突, 如A.a和B.a来⾃两个名称空间

posted @ 2018-11-20 15:28  一片疏影  阅读(165)  评论(0编辑  收藏  举报