Python之模块与包(下)
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.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)包所包含的文件內容 文件內容 from . import api # 告訴調用 glance 包的模塊,找api 的話從你自己的 sys.path 下 glance 下開始找 api glance包 __init__ 的文件內容 # print('from api init.py') # __all__=['x','y','policy'] # all 方法對應 # x=1 # y=2 from . 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 glance glance.api.policy.get()# 如果是導入跟“包”同級的aaa包下的 glacne,就要先找到兩者的父級目錄,再從父級目錄開始找 import os import sys base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) print(base_dir) # 父級目錄 sys.path.append(base_dir) from aaa.glance.api import policy policy.get() 跟 glance 同級的文件 test.py?
例2:
if __name__=='__main__': # 表示把自己當做腳本去用print('ok')如果我們是直接執行某個.py文件的時候,該文件中那么”__name__ == '__main__'“是True,但是我們如果從另外一個.py文件通過import導入該文件的時候,這時__name__的值就是我們這個py文件的名字,而不是__main__。
這個功能還有一個用處:調試代碼的時候,在”if __name__ == '__main__'“中加入一些我們的調試代碼,我們可以讓外部模塊調用的時候不執行我們的調試代碼,但是如果我們想排查問題的時候,直接執行該模塊文件,調試代碼能夠正常運行!
logger.py def logging():print('ok')mian.py from core import logger def main():logger.logging()# print(__name__) if __name__ == '__main__':main()bin.py import os,sys base_dir=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 添加ATM的絕對路徑 # print(base_dir) sys.path.append(base_dir) # 把路徑添加到系統環境變量里去from core import main main.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()
.
轉載于:https://www.cnblogs.com/tootooman/p/9071402.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Python之模块与包(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 潭州课堂25班:Ph201805201
- 下一篇: Python基础—08-函数使用(02)