包,Package,是一種Python模塊的集合,從文件組織形式上看,包就是一個文件夾,裏面放着各類模塊(.py文件),也能夠有子文件夾(子包)。包名構建了一個Python模塊的命名空間。好比,模塊名A.B
表示A
包中名爲B
的子模塊。這種使用加點的模塊名可讓你寫的軟件包裏面的模塊名稱和其它軟件包裏面的模塊名稱同樣,但又不相互衝突。python
舉個栗子,咱們要設計一個處理圖片的模塊集合(一個包)。咱們知道,圖片有多種不一樣的文件格式,通常它們以不一樣的擴展名來識別,好比.jpg
,.png
,.gif
等等。爲了讀寫不一樣格式的圖片,你須要對每一種格式創建一個對應的模塊進行處理,爲了支持更多的圖片格式,你就要增長更多對應的模塊。對於圖片你可能還有更多的處理,好比,改變色彩,裁剪,旋轉等等,爲了實現這些功能,你又要寫更多的模塊。這樣下來,你的包的結構以文件系統的形式表示以下:spa
image # 頂級包 ├── __init__.py # 初始化image包 ├── formats # 圖片格式的子包 │ ├── gif_read.py │ ├── gif_write.py │ ├── __init__.py │ ├── jpg_read.py │ ├── jpg_write.py │ ├── png_read.py │ └── png_write.py └── process # 圖片處理的子包 ├── colors.py ├── crop.py ├── __init__.py └── rotate.py
爲了讓目錄成爲Python的包,目錄中必須含有一個__init__.py
文件,它能夠是空文件但不能不存在。這樣作的目的是爲了仿照具備通用名稱的目錄無心中隱藏了在模塊搜索路徑排在後面的有效模塊。好比,你當前目錄下有個time
目錄是放程序資源的,它裏面沒有__init__.py
文件就是一個普通的目錄。若是Python不要求包目錄下必須含有__init__.py
文件,它就會隱藏Python系統的time模塊。設計
前面說了,包的目錄中必須包含一個__init__.py
文件,它能夠是空文件,也能夠寫包初始化相關的代碼,或者定義__all__
變量。code
__all__
變量是一個列表,它列舉了這個包包含的子模塊的名稱。當from package import *
語句執行時,會把這個模塊名稱列表裏面的模塊名稱導入。因此說__all__
是一個包的顯示索引。若是你以爲從包中導入*
的操做不必被使用,也能夠不定義__all__
這個變量。orm
例如,文件image/process/init.py能夠包含如下代碼:索引
__all__ = ['colors', 'crop', 'rotate']
定義了__all__
以後,from image.process import *
就會把colors
,crop
,rotate
導入到當前命名空間。圖片
實際寫代碼的實踐中,import *
的作法是嚴格被禁止的,它容易形成包中模塊名與當前命名空間的名稱衝突。資源
更推薦的方法是from package import submodule
或from package import submodule as alias_for_submodule
。固然,若是兩個包中有同名的submodule,就不能同時使用from package import submodule
,但能夠取個別名。圖片處理
導入包的方法和導入模塊的方法同樣:rem
import image
在程序中引用colors
子模塊時:
image.process.colors(...)
接下來,看看咱們如何導入一個包中某單個模塊:
import image.process.colors
這樣就加載了子模塊image.process.colors
,在程序中使用時必須使用它的全名,而不是簡單的colors
。
若是想使用colors
這個名字,就用這種導入語句:
from image.process import colors
當包含有子包時(與例子中的image包相似),咱們可使用絕對導入來引用兄弟包的子模塊。好比,若是模塊 image.process.crop 須要使用 image.formats 包中的 jpg_read 模塊時,它可使用 from image.formats import jpg_read
。
咱們也可使用 from module import name
的形式相對導入。這種導入使用前導點.
來指示相對導入中涉及的當前包
和父包
。好比,在 crop 模塊中,你可使用:
from . import colors from .. import formats from ..formats import jpg_read
請主要,相對導入是基於當前模塊的名字進行導入的。因爲主模塊(即被python 執行的那個.py文件)的名稱老是"__main__"
,所以用做Python應用程序的主模塊的模塊必須用絕對導入。也就是說被執行的主程序裏面不能包含相對導入。這一點很重要,切記!