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
相關文章
相關標籤/搜索