Python之模組與包(下)

來源:互聯網
上載者:User

標籤:ada   就會   one   檔案   二層   closed   main   not   img   

1、什麼是包

#官網解釋

Packages are a way of structuring Python’s module namespace by using “dotted module names”

包是一種通過使用‘.模組名’來組織python模組名稱空間的方式。

#具體的:包就是一個包含有__init__.py檔案的檔案夾,所以其實我們建立包的目的就是為了用檔案夾將檔案/模組組織起來

#需要強調的是:

  1. 在python3中,即使包下沒有__init__.py檔案,import 包仍然不會報錯,而在python2中,包下一定要有該檔案,否則import 包報錯

  2. 建立包的目的不是為了運行,而是被匯入使用,記住,包只是模組的一種形式而已,包的本質就是一種模組

2、為何要使用包

包的本質就是一個檔案夾,那麼檔案夾唯一的功能就是將檔案組織起來

隨著功能越寫越多,我們無法將所以功能都放到一個檔案中,於是我們使用模組去組織功能,而隨著模組越來越多,我們就需要用檔案夾將模組檔案組織起來,以此來提高程式的結構性和可維護性

3、注意事項

#1、關於包相關的匯入語句也分為import和from ... import ...兩種,但是無論哪種,無論在什麼位置,在匯入時都必須遵循一個原則:凡是在匯入時帶點的,點的左邊都必須是一個包,否則非法。可以帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。但對於匯入後,在使用時就沒有這種限制了,點的左邊可以是包,模組,函數,類(它們都可以用點的方式調用自己的屬性)。

例:import spam.x

匯入前:import spam.x:如果 spam 是一個模組,就會報錯,spam 必須是一個包

匯入後:spam.x 直接調用模組 spam 下的 x 屬性

#2、import匯入檔案時,產生名稱空間中的名字來源於檔案,import 包,產生的名稱空間的名字同樣來源於檔案,即包下的__init__.py,匯入包本質就是在匯入該檔案

調用包就是執行包下的__init__.py檔案

#3、包A和包B下有同名模組也不會衝突,如A.a與B.a來自倆個命名空間

 

4、例子

例1:

glance/                   #Top-level package  大包├── __init__.py      #Initialize the glance package├── api                  #Subpackage for api  小包│   ├── __init__.py│   ├── policy.py│   └── versions.py├── cmd                #Subpackage for cmd 小包│   ├── __init__.py│   └── manage.py└── db                  #Subpackage for db 小包    ├── __init__.py    └── models.py
目錄結構
#policy.pydef get():    print(‘from policy.py‘)#versions.pydef create_resource(conf):    print(‘from version.py: ‘,conf)#manage.pydef main():    print(‘from manage.py‘)#models.pydef register_models(engine):    print(‘from models.py: ‘,engine)包所包含的檔案內容
檔案內容
from . import api# 告訴調用 glance 包的模組,找api 的話從你自己的 sys.path 下 glance 下開始找 api
glance包 __init__ 的檔案內容
# print(‘from api init.py‘)# __all__=[‘x‘,‘y‘,‘policy‘]   # all 方法對應 # x=1# y=2from . import policy# 告訴那個匯入 api包的模組(test),找 policy 的時候,從他自己的 sys.path 開始找# import policy# 絕對匯入# 告訴那個匯入 api包的模組(test),找 policy 的時候,從他自己的 sys.path 下的 glance.api 開始找# from glance.api import policy# 相對匯入# 從目前的目錄開始找 policy 模組# from . import policy# 幫 test 找到 manage 模組# from ..cmd import manage# 直接運行此檔案會報錯,# SystemError: Parent module ‘‘ not loaded, cannot perform relative import# 父模組沒有被載入,不能使用相對匯入的意思# 說明包裡面的模組不應該作為單獨檔案直接運行
api包 __init__ 的檔案內容
# 例1:直接 import 包方式匯入模組# import glance.api.policy  # 匯入 blance包下的api包下的policy模組# glance.api.policy.get()   # 執行 policy下的 get 方法# 例2:比較直觀的用法# from glance.api import policy  # from 大包.小包 import 模組# policy.get()# from glance.api import policy.get  # 不能這樣用,報 SyntaxError: invalid syntax 語法錯誤# get()# from glance import api.policy# 雖然滿足點左邊的是包,但是這裡是 from ... import,import後面必須明確一個不能帶點的東西#需要注意的是from後import匯入的模組,必須是明確的一個不能帶點東西,否則會有語法錯誤# 如:from a import b.c 是錯誤文法# api 的 init 檔案# from glance.api import policy# 當匯入包的時候,只會執行 api 包下面的 init 檔案# policy.get()# * 的意義# from glance.api import *# 匯入包,依然會執行 init 檔案,但是這裡的 * 不代表 api 包下所有的模組# * 是指 api 下 init 裡面 __all__ 裡麵包含的屬性,屬性可以是任何,模組,變數等等# import glance.api # 匯入包就執行 glance 和 api 包 init 檔案# print(glance.api.policy)# 但是 policy 依然沒有,因為這裡只是匯入包,執行 init,不會觸發 all 方法# import glance.api  # 觸發 api 下的 init 檔案# print(glance.api.policy)  # ImportError: No module named ‘policy‘# init 下有 import policy# 先從記憶體裡找 policy,然後從內建裡找,最後從當前 test 所在的 sys.path 裡找 policy 模組,找不到,報錯# 讓 api 包幫我找到 manage 模組# glance.api.manage.main()import glanceglance.api.policy.get()# 如果是匯入跟“包”同級的aaa包下的 glacne,就要先找到兩者的父級目錄,再從父級目錄開始找import osimport sysbase_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))print(base_dir) # 父級目錄sys.path.append(base_dir)from aaa.glance.api import policypolicy.get()
跟 glance 同級的檔案 test.py

 

例2:

if __name__==‘__main__‘: # 表示把自己當做指令碼去用    print(‘ok‘)

如果我們是直接執行某個.py檔案的時候,該檔案中那麼”__name__ == ‘__main__‘“是True,但是我們如果從另外一個.py檔案通過import匯入該檔案的時候,這時__name__的值就是我們這個py檔案的名字,而不是__main__。

這個功能還有一個用處:調試代碼的時候,在”if __name__ == ‘__main__‘“中加入一些我們的調試代碼,我們可以讓外部模組調用的時候不執行我們的調試代碼,但是如果我們想排查問題的時候,直接執行該模組檔案,調試代碼能夠正常運行!

logger.pydef logging():    print(‘ok‘)mian.pyfrom core import loggerdef main():    logger.logging()# print(__name__)if __name__ == ‘__main__‘:    main()bin.pyimport os,sysbase_dir=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # 添加ATM的絕對路徑# print(base_dir)sys.path.append(base_dir)  # 把路徑添加到系統內容變數裡去from core import mainmain.main()
例子

現象:

1、當執行 bin.py 的時候會顯示 ok,正常運行,單獨執行 main.py 正常顯示一個 ok

2、當 main.py 注釋 if __name__ == ‘__main__‘,執行 bin.py 會顯示兩個 ok,單獨執行 main.py 正常顯示一個 ok

3、當 main.py 只有 print(__name__),執行 bin.py 只顯示 main,執行 main.py 顯示 __main__

結論:

1:if __name__ == ‘__main__‘ 是用來調試用的,在別的地方調用該模組執行的使用不會執行被調用模組下的 if __name__ == ‘__main__‘ 下的代碼

2:在被調用模組下執行程式,會執行 if __name__ == ‘__main__‘ 下的代碼,因為是自己的地方,方便調試

 

5、包的2種調用方式

logger.py 檔案內容

def logger():    print(‘logger‘)

# from web.web2 import logger # 二層目錄

調用 logger 模組裡的 logger方法

logger.logger()

# from web.web2.logger import logger # 調用 web包下的 web2包下的logger 模組的 logger 方法,直接用 Logger()

直接調用 logger 模組裡的 logger方法

logger()

.

Python之模組與包(下)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.