包的详解

  在python中,包是一种管理模块的组织方式。凡是无论在import和from...import中遇到".模块名"的形式,这种带点的就是导入包的才有的导入语法。

  含有一个__init__.py文件的文件夹,就是一个包。导入包的本质其实就是导入__init__.py这个文件。

  例子:首先先部署好今天的环境:

#例子:巧用map函数创建目录
'''
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/version.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/models.py','w'))
map(lambda f:f.close(),l)  

结果:
day26
    --glance
        --__init__.py
        --api
            --__init__.py
            --policy.py
            --version.py
        --cmd
            --__init__.py
            --manage.py
        --db
            --models.py
'''
包的层级

 1.从包中导入模块

  从包中导入模块的也有两种方式(无论哪种方式,都要谨记,点的左边必须是包)

  (1)import

  例如: 包名1.包名2.包名3.模块名

  (2)from...import

  例如:from 包名1.包名2 import 模块名

      from 包名1.包名2.模块名 import 变量名/函数名/变量名

 2.直接导入包

'''
情景1:
    既然导入包就是执行包下的__init__.py文件,那么尝试下在glance的
__init__.py文件中"import api",执行一下,貌似没有报错,在尝试下在包外导入,情况如何?
    import glance
    glance.api
ModuleNotFoundError: No module named 'api'

原因:
为什么还会报错呢?还记得sys.path,一个模块能不能被导入就看在sys.path中有没有路径,在哪里执行文件,sys.path永远记录是该文件的目录。
    (1)在glance的__init__.py文件中,sys.path的路径是:
   'E:\python_training_s1\old_boy_training\day26\glance'
    所以能够找到同层级的api。
    (2)但是在day26_training.py文件中导入,此时sys.path的路径是:
    'E:\python_training_s1\old_boy_training\day26'
    所以找不到不同层级的api,所以就会报NO module named 'api'
    
解决方法:
    使用绝对路径(绝对路径为当前执行文件的目录):
    (1)在glance包中的__init__.py中通过绝对路径的形式导入:
        “from glance import api”
    (2)这样在day26_training.py中执行,就能找到同层级的glance,再去找里面的api
    (3)同理,如果想使用api包中的模块,也要在api包中的__init__.py文件中导入"from glance.api import police,version"
    
绝对导入的缺点:
    如果以后包的路径发生了转移,包内的所有__init__.py文件中的绝对路径都需要改变
'''
# import glance
# glance.api
# import glance
# glance.api.policy.get()
#
# from glance.api.version import create_resource
# create_resource('dkfjk')

# from glance.api import policy
# policy.get()
'''
解决方式二:相对导入
    # .点表示当前目录
    # ..点表示上一级目录
(1)在glance包中的__init__.py中通过相对路径的形式导入:
     “from . import api”
(2)同理在api包中的__init__.py中通过相对路径的形式导入:
     “from . import policy,version”

优点:
    包发生路径转移,其中的相对路径都没有改变,所以不用逐个逐个修改。

缺点:
    但凡带着相对导入的文件,只能当做模块导入,不能作为一个脚本单独执行!!!
'''
# import glance
# glance.api.policy.get()

  

原文地址:https://www.cnblogs.com/hebbhao/p/9605984.html