Python基礎(十八)
- 2019 年 10 月 7 日
- 筆記
今日主要內容
- 包
一、包
(一)什麼是包
- 只要是含有
__init__.py文件的文件夾就是一個包 - 包的本質其實就是一個文件夾,利用包將不同功能的模組組織起來,以此來提高程式的結構性和可維護性
- 包是用來導入的,不是用來執行的,所以它和軟體開發規範分文件管理還是有區別的,一個是項目,一個是用來導入的包
- 正因為包是用來導入的,所以運行文件一定要放在包的外面
(二)創建一個包
利用程式碼創建一個包
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/test.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/models.py','w')) map(lambda f:f.close() ,l)- 下述所有內容,均以此圖結構為基礎

(三)__init__.py文件
在我們導入包的時候,其實本質上導入的就是
__init__.py文件,解釋器會自動執行__init__.py文件中的內容# glance/__init__.py print("這裡是glance下的__init__.py文件") # run.py import glance 運行結果: 這裡是glance下的__init__.py文件
(四)包的導入
- 包的導入,須注意兩點內容:
- 導入時無論是使用
import還是使用from xxx import xxx導入,點的前面必須是一個包 - 使用
from xxx import xxx導入時,import前可以出現點,import後不能出現點
- 導入時無論是使用
常規導入
- import導入
# policy.py def policy_func(): print("這是policy文件中的函數") # run.py import glance.api.policy glance.api.policy.policy_func() 運行結果: 這是policy文件中的函數 # 成功導入- from import導入
# policy.py def policy_func(): print("這是policy文件中的函數") # run.py from glance.api.policy import policy_func policy_func() 運行結果: 這是policy文件中的函數 # 成功導入包內部之間的導入:
包內部之間的相互引用,只能用絕對導入和相對導入,不能直接導入,比如
policy.py文件需要導入versions.py文件中的函數,如果直接import導入會報找不到該模組的錯誤- 包內部互相引用的時候不能直接導入
# versions.py def versions_func(): print("這是versions文件中的函數") # policy.py import versions # 直接導入versions模組,在外面的run文件中運行,就無法找到versions模組 def policy_func(): versions.versions_func() print("這是policy文件中的函數") # run.py from glance.api import policy policy.policy_func() 運行結果: ModuleNotFoundError: No module named 'versions'- 原因分析:如果直接在policy文件中運行程式,完全沒有問題,因為此時policy文件的模組查找路徑中包含versions模組,但是**包是用來導入的,如果在包外的run文件中導入policy模組,此時模組查找路徑就變為了run文件所在的路徑,所以當policy文件導入versions模組時,路徑下並沒有versions模組,所以找不到該模組
絕對導入:
# versions.py def versions_func(): print("這是versions文件中的函數") # policy.py from glance.api import versions def policy_func(): versions.versions_func() print("這是policy文件中的函數") # run.py from glance.api import policy policy.policy_func() 運行結果: 這是versions文件中的函數 這是policy文件中的函數- 相對導入:
# versions.py def versions_func(): print("這是versions文件中的函數") # policy.py from . import versions def policy_func(): versions.versions_func() print("這是policy文件中的函數") # run.py from glance.api import policy policy.policy_func() 運行結果: 這是versions文件中的函數 這是policy文件中的函數- 只要使用了相對導入的模組,只能作為模組使用,不能作為腳本(終端中直接運行的文件成為腳本)使用,說白了就是不能直接運行
# versions.py def versions_func(): print("這是versions文件中的函數") # policy.py from . import versions def policy_func(): versions.versions_func() print("這是policy文件中的函數") 運行結果: ImportError: cannot import name 'versions'單獨導入包,並使用包內的包或模組
- 單獨導入一個包,其本質上導入的只是
__init__.py文件,包中其他的文件並沒有被導入
# policy.py def policy_func(): print("這是policy文件中的函數") # run.py import glance # 只導入了__init__.py文件 glance.api.policy.policy_func() # 並不能使用 運行結果: AttributeError: module 'glance' has no attribute 'policy'- 此時就要利用到
__init__.py文件了,__init__.py文件在包中起到了交接管理的作用,可以在__init__.py文件中導入每個子文件,也可以控制其是否能被導入,所以每一個包中必須要有__init__.py文件
# policy.py def policy_func(): print("這是policy文件中的函數") # glance/__init__.py from . import api # glance/api/__init__.py from . import policy # run.py import glance glance.api.policy.policy_func() 運行結果: 這是policy文件中的函數- 直接調用模組中的方法
# policy.py def policy_func(): print("這是policy文件中的函數") # glance/__init__.py from .api import * # glance/api/__init__.py from .policy import * # run.py import glance glance.policy_func() 運行結果: 這是policy文件中的函數還可以通過
__all__來控制模組和模組中函數的導入- 控制模組導入
# glance/__init__.py from .api import * # glance/api/__init__.py __all__ = ["versions"] # 只能導入versions,其餘api下模組都不能被導入 # run.py import glance glance.policy 運行結果: AttributeError: module 'glance' has no attribute 'policy'- 控制方法導入
# policy.py def policy_func(): print("這是policy文件中的func") def policy_foo(): print("這是policy文件中的foo") # glance/__init__.py from .api import * # glance/api/__init__.py from .policy import * __all__ = ["policy_foo"] # 控制只能導入foo函數,其餘函數都不能被導入 # run.py import glance glance.policy_func() 運行結果: AttributeError: module 'glance' has no attribute 'policy_func'
- 單獨導入一個包,其本質上導入的只是