Packages

1、package

    包是一种经过".模块名"来组织python模块名称空间的方式。咱们建立的每一个文件夹均可以被称之为包。python2中规定,包内必须存在__init__.py文件。建立包的目的不是为了运行,而是被导入使用。包只是一种形式而已。python

  • 本质:一种模块

1.被称之为包所具有的条件:

  • 文件夹
  • 有__init__.py文件(python2中必须有,python3可省略,但最好保留)

2. 导入包时执行的三个动做

  • 判断文件夹是否已经被导入。若是已导入,则不会再重复导入,也就不会执行下面两个操做
  • 开辟一片内存空间,在该空间中执行包的__init__.py文件
  • 建立包的名字。并使用该名称做为该包在当前模块中引用的名字

3. 包的注意事项:

  • 关于包相关的导入语句也分为import和from xxx import xxx两种,但不管使用哪一种,不管在什么位置,在导入时都必须遵循一个原则:凡是在导入带点的,点左边都是一个包,不然报错。能够带一连串的点,如a.b.c
  • import导入文件时,产生名称空间中的名字来源于文件。import包,产生的名称空间中的名字一样来源于文件。即包下的__init__.py文件,导入包的本质就是导入该文件。
  • 包A和包B下同名模块也不会冲突。如A.a和B.a来自两个不一样的名称空间
  • 导包时,需注意sys.path路径范围,不然易超出范围而报错。
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)

获得以下目录结构:mysql

各文件中写有以下内容:sql

# 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)

2、包的导入方式

1. import xxx

# 与glance文件夹同目录下test.py
import glance.db.models

glance.db.models.register_models("mysql")


结果:
from models.py:  mysql

2. from xxx import xxx

    采用from xxx import xxx这种形式,import后面不能够出现"."。也就是说,from a.b import c是正确的,而from a import b.c是错误的api

# 与glance文件夹同目录下test.py
from glance.db.models import register_models

register_models("mysql")

结果:
from models.py:  mysql

 3、 __init__.py

    不论使用哪一种方式导入一个包,只要是第一次导入包或者是包的任何其它部分。都会先执行__init__.py文件。app

# glance文件夹下的__init__.py文件
print("我是glance的__init__.py文件")
# 与glance文件夹同目录下test.py
import glance


结果:
我是glance的__init__.py文件

4、绝对导入

    绝对导入,是按sys.path路径寻找包,若是包不在sys.path列表中,可将包移至路径中。也可append包路径到sys.path中,但通常不这样作。spa

# policy.py
from glance.api.versions import create_resource

def get():
    create_resource("mysql")
    print("from policy.py")
# 与glance文件夹同目录下的test.py
from glance.api.policy import get

get()

结果:
我是glance的__init__.py文件
from version.py:  mysql
from policy.py

5、相对导入

    在相对导入中,python不容许你运行的程序导包的时候超过当前包的范围。code

# policy.py
from ..cmd import manage

def get():
    manage.main()
    print("from policy.py")

get()

结果:
ValueError: attempted relative import beyond top-level package

    若是在包内使用了相对导入,那么在使用该包内信息的时候,只能在包外面导入blog

在包内导入则报错:内存

# policy.py
from . import versions

def get():
    versions.create_resource("mysql")
    print("from policy.py")

get()

结果:
ImportError: cannot import name 'versions'

在包外导入,运行成功:get

# policy.py
from . import versions

def get():
    versions.create_resource("mysql")
    print("from policy.py")
# 与glance文件夹同目录下的test.py
from glance.api.policy import get

get()


结果:
我是glance的__init__.py文件
from version.py:  mysql
from policy.py

 6、单独导入一个包

   单独导入一个包glance,,若是在包中__init__.py文件中并无关于子包的加载,此时导入的glance什么都作不了。

    在__init__.py中加载子包可使用绝对路径加载,也可以使用相对路径加载

# glance文件夹下的__init__.py文件


from glance import api
# glance/api/__init__.py文件

from glance.api import policy
# glance/api/policy.py

def get():
    print("from policy.py")
# 与glance文件夹同目录下的test.py
import glance

glance.api.policy.get()


结果:
from policy.py
相关文章
相关标签/搜索