Python的模塊(module)和包(package)
Python的模塊(module)和包(package)概述
在Python中,簡單地說,模塊(Module)一般是單個(gè)python文件;包(package)由分層模塊(Module)構(gòu)成——相關(guān)目錄里的模塊構(gòu)成。Python中的庫(library)是參考其它編程語言的說法,既可以是一個(gè)模塊也可以是一個(gè)包,換言之是對模塊或包的通俗的說法。
模塊(module)其實(shí)就是py文件【注1】,里面定義了一些函數(shù)、類、變量等。模塊的名字就是該文件的名字(不包含后綴)。
【注1:Python 中的模塊,往往對應(yīng)于Python 程序文件。每一個(gè)文件都是一個(gè)模塊。模塊也可以是使用如 C、 Java或C#等其他語言編寫的擴(kuò)展包,甚至還可以是在包導(dǎo)入時(shí)的文件路徑。一般情況下,是一個(gè)以.py為后綴的文件,其他可作為module的文件類型還".pyo"、".pyc"、".pyd"、".pyw"、".dll",但Python初學(xué)者幾乎用不到?!?/p>
模塊的分類【注2】:標(biāo)準(zhǔn)模塊(庫)、第三方模塊(庫)、自定義模塊。
自定義模塊就是你自己編寫的模塊,如自己定義的函數(shù),需要經(jīng)常調(diào)用時(shí),就可以自己定義一個(gè)模塊,將常用函數(shù)、類、變量等寫入模塊里,另外的模塊若要使用,使用import語句導(dǎo)入該模塊,就可以使用了。第三方模塊的數(shù)量非常龐大,有許多非常有名并且影響廣泛的模塊。第三方模塊需要安裝(詳情可見 https://blog.csdn.net/cnds123/article/details/104393385),再使用import語句導(dǎo)入后使用。標(biāo)準(zhǔn)模塊(庫)是安裝Python時(shí)自動(dòng)安裝在Python安裝路徑的Lib文件夾中,不需要用戶安裝,可以直接使用import語句導(dǎo)入后使用。
【注2;還有一個(gè)分類內(nèi)置模塊(built-in module),內(nèi)置模塊是用C寫的,提供了對系統(tǒng)功能的訪問。從Python的標(biāo)準(zhǔn)庫路徑下面是找不到的。雖然內(nèi)置模塊不是標(biāo)準(zhǔn)庫,但是內(nèi)置模塊可以劃分到標(biāo)準(zhǔn)庫一類中去,這里需要注意的是劃分歸類,而不是本質(zhì)相同。大多數(shù)情況下,對它們之間沒有做區(qū)分的必要。但是在理解Python的模塊查找順序時(shí),這卻是一個(gè)主要的差異。https://www.cnblogs.com/pluse/p/8667864.html】
包(package)是多個(gè)模塊的聚合體形成的文件夾,里面可以是多個(gè)py文件,也可以嵌套文件夾。import 語句中的目錄路徑只能是以點(diǎn)號間隔的——子包名與其父包名會(huì)以點(diǎn)號分隔。
可以把包看成是文件系統(tǒng)中的目錄,并把模塊看成是目錄中的文件。包通過層次結(jié)構(gòu)進(jìn)行組織,在包之內(nèi)除了一般的模塊,還可以有子包。
Python 定義了兩種類型的包,即 常規(guī)包(regular packages) 和 命名空間包(namespace packages)。常規(guī)包是存在于 Python 3.2 及更早版本中的傳統(tǒng)包。常規(guī)包即包含 __init__.py 文件的目錄。當(dāng)導(dǎo)入一個(gè)常規(guī)包時(shí),__init__.py 文件被隱式執(zhí)行,而且它定義的對象被綁定到包命名空間中的名稱。 __init__.py 文件能包含其他任何模塊能夠包含的相同的 Python 代碼,而且在導(dǎo)入時(shí),Python 將給模塊增加一些額外的屬性。
從 Python 3.3 開始,Python 引入了 命名空間包 的概念。命名空間包是不同文件集的復(fù)合,每個(gè)文件集給父包貢獻(xiàn)一個(gè)子包,所有的包中都不需要包含 __init__.py 文件。文件集可以存于文件系統(tǒng)的不同位置。文件集的查找包含導(dǎo)入過程中 Python 搜索的壓縮文件,網(wǎng)絡(luò)或者其他地方。命名空間包可以但也可以不與文件系統(tǒng)的對象直接對應(yīng)。命名空間包提出的本意卻不是說為了導(dǎo)入沒有init.py 的文件夾的 Python 模塊,而是利用命名空間包這個(gè)技術(shù)來導(dǎo)入目錄分散的代碼。
順便提示:所有包都是模塊,但并非所有模塊都是包。換句話說,包只是一種特殊的模塊。具體來說,任何包含__path__屬性的模塊都被視為包。
【官方文檔:6. 模塊 — Python 3.10.7 文檔
5. 導(dǎo)入系統(tǒng) — Python 3.10.7 文檔 】
這兩個(gè)概念,有助于我們更好地使用python進(jìn)行模塊化編程,通過模塊化編程,我們能把大的工程拆分成子任務(wù)(子模塊),好處是,可維護(hù)性好,問題也便于排查;編寫好的模塊復(fù)用性好,當(dāng)需要重復(fù)實(shí)現(xiàn)時(shí),再次調(diào)用即可,不必再重新編寫了;每個(gè)模塊都有單獨(dú)的命名空間,避免發(fā)生一些例如變量、函數(shù)命名上的沖突??捎糜趐ython復(fù)雜程序的組織【https://blog.csdn.net/cnds123/article/details/108614392 】。
Python的模塊、包的導(dǎo)入使用
import 語句有兩種形式
基本的 import 語句(不帶 from 子句)和 帶 from 子句的import 語句。
基本的 import 語句(不帶 from 子句)格式:
import 模塊名 [as 別名]
對于包
import 包名.模塊名 [as 別名]
其中,對于包中含包的包名之間英文句號分隔。
使用戶程序(導(dǎo)人者)以一個(gè)整體獲取一個(gè)模塊,這種形式想使用模塊或包中的成員(模塊中的函數(shù)、類、變量)需要加前綴:“模塊名.”、 “包名.模塊名.”或 “別名.”
帶 from 子句的import 語句格式:
from 模塊名 import 成員名 [as 別名]
其中,成員名可以有多個(gè),之間用英文逗號分隔
對于包
from 包名.模塊名 import 成員名 [as 別名]
允許用戶程序從一個(gè)模塊文件中獲取特定的名稱 ,這種形式因已指出了成員名,這種形式想使用模塊或包中的成員可以直接使用成員名無需加前綴,若為成員名指定了別名,可以直接使用別名無需加前綴。
導(dǎo)入包的方法與導(dǎo)入模塊的方法類似,需要注意的只是要用點(diǎn)號語法指明路徑層次——import 語句中的目錄路徑只能是以點(diǎn)號間隔。
【import語句的用法可參照https://www.jb51.net/article/238794.htm 】
補(bǔ)充說明
1)可以一次導(dǎo)入多個(gè)模塊,多個(gè)模塊之間用逗號隔開,如:import sys,os
2)在導(dǎo)入多個(gè)模塊的同時(shí),也可以為模塊指定別名,如導(dǎo)入sys、os兩個(gè)模塊,并為sys指定別名s,為os指定別名o:
import sys as s,os as o
3)導(dǎo)入模塊成員時(shí),也可以為成員指定別名,如導(dǎo)入sys模塊的argv成員,并為其指定別名v,這樣就可以直接使用成員的別名訪問:
from sys import argv as v
print(v[0]) ?#就相當(dāng)于 print(argv[0])
3)可以 *代表多有成員,此方式不推薦使用
比如同時(shí)導(dǎo)入 module1 和 module2 內(nèi)的所有成員:
from module1 import *
from module2 import *
假如這兩個(gè)模塊內(nèi)都有一個(gè) foo() 函數(shù),那么當(dāng)在程序中執(zhí)行如下代碼時(shí):
foo()
上面調(diào)用的這個(gè) foo() 函數(shù)到底是 module1 模塊中的還是 module2 模塊中的?因此,這種導(dǎo)入指定模塊內(nèi)所有成員的用法是有風(fēng)險(xiǎn)的。
4)import語句是最常用的導(dǎo)入機(jī)制,但并不是唯一的方式,importlib 模塊以及內(nèi)置的__import__() 方法都可以實(shí)現(xiàn)模塊的導(dǎo)入。
import的搜索順序
當(dāng)import語句導(dǎo)入后,默認(rèn)情況下,搜索模塊的路徑為:首先判斷這個(gè)module是不是built-in module(內(nèi)置模塊,見前面【注2】),然后:
1)當(dāng)前目錄的路徑
2)環(huán)境變量 PYTHONPATH 中指定的路徑列表
3)Python 安裝路徑
可以利用sys.path查看當(dāng)前的搜索路徑
import sys
sys.path
說明,sys.path在python腳本執(zhí)行時(shí)動(dòng)態(tài)生成,一個(gè)由字符串組成的列表,用于指定模塊的搜索路徑。一般來說,第三方庫會(huì)安裝在site-packages路徑下。列表的第一項(xiàng) path[0] 若為空字符串,這將導(dǎo)致 Python 優(yōu)先搜索當(dāng)前目錄【注3】中的模塊。
【注3:當(dāng)前正在使用的目錄稱為當(dāng)前目錄(或者工作目錄)。執(zhí)行程序的編譯和運(yùn)行時(shí),執(zhí)行對象所在的目錄基本上就被視為當(dāng)前目錄?!?/p>
要修改import搜索路徑有多種方式:
1)臨時(shí)添加,即動(dòng)態(tài)修改 sys.path,因?yàn)?sys.path 為 list,所以我們可以很輕松的操作 list 實(shí)現(xiàn)搜索路徑的修改。這種方式只會(huì)對當(dāng)前項(xiàng)目臨時(shí)生效——只在執(zhí)行當(dāng)前文件的窗口中有效,窗口關(guān)閉后即失效。
import sys
sys.path.append('D:/demo/python_module')
其中,'D:/demo/python_module' 也可寫為 'D:\\demo\\python_module'
Python代碼使用的路徑中若使用的 '\' 需要使用 \ 進(jìn)行轉(zhuǎn)義寫為\\
2)修改 PYTHONPATH 環(huán)境變量,這種方式會(huì)永久生效,而且所有的 Python 項(xiàng)目都會(huì)受到影響,因?yàn)?Python 程序啟動(dòng)時(shí)會(huì)自動(dòng)去讀取該環(huán)境良好的值。
不同平臺(tái)設(shè)置流程不盡相同,這里以windows10操作系統(tǒng)中為例:按WIN+R鍵,打開“運(yùn)行”對話框,輸入sysdm.cpl,按回車鍵也能打開“系統(tǒng)屬性”對話框,“高級”選項(xiàng)卡中,單擊“環(huán)境變量”按鈕,單擊系統(tǒng)變量中的“新建”按鈕,在“變量名”文本框內(nèi)輸入 PYTHONPATH,表明將要建立名為 PYTHONPATH 的環(huán)境變量;在“變量值”文本框內(nèi)輸入D:\demo\python_module
然后點(diǎn)擊“確定”。重啟系統(tǒng)才能使之生效。這種方法添加的路徑可以對安裝的多個(gè)不同版本的Python都生效。
3)增加.pth 后綴的文件。在 sys.path 已有的某一個(gè)目錄下添加.pth 后綴的配置文件,該文件的內(nèi)容就是要添加的搜索路徑,Python 在遍歷已有目錄的過程中,如果遇到.pth 文件,就會(huì)將其中的路徑添加到 sys.path 中。
Python 在遍歷已知的庫文件目錄過程中,如果見到一個(gè) .pth 文件,就會(huì)將文件中所記錄的路徑加入到 sys.path 設(shè)置中,于是 .pth 文件所指明的庫也就可以被 Python 運(yùn)行環(huán)境找到了。這個(gè)文件雖然可以放在python的已知庫文件的目錄里面就可以了,不過我還是建議統(tǒng)一放到python安裝目錄的site-packages目錄中。
主文件名是沒有限制的,你可以根據(jù)自己的庫內(nèi)容進(jìn)行定義,只要擴(kuò)展名為.pth就可以了。文件內(nèi)容一般只要設(shè)置一下路徑就可以,可以是相對路徑(相對于.pth所在的路徑),也可以是絕對路徑。如用記事本建立一個(gè)名為mypath.pth文件,添加內(nèi)容(根據(jù)你實(shí)際需要寫)如D:\demo\python_module,放到python安裝目錄的site-packages目錄中。
4)將模塊保存到指定位置
可以直接將我們已編寫好的py 文件添加到Python安裝路徑中的lib\site-packages 路徑下,就相當(dāng)于為 Python 擴(kuò)展了一個(gè) 模塊,這樣任何 Python 程序都可使用該模塊。
使用模塊(module)和包(package)的例子
下面給出一個(gè)簡單而完整的示例項(xiàng)目,其目錄結(jié)構(gòu)如下
其中,call_test2.py 要導(dǎo)入使用first.py和abcd.py
first.py文件的內(nèi)容如下:
a = 1.5
def myfun(s):
return(s + 1)
abcd.py文件的內(nèi)容如下:
a = 20
def myfun(s):
return(s*s)
?call_test2.py文件的內(nèi)容如下:
import first
import folder1.abcd as second
print(first.a) #顯示1.5
x=3
print(first.myfun(x)) #顯示4
print("----------")
print(second.a) #顯示20
y=5
print(second.myfun(5)) #顯示25
運(yùn)行call_test2.py,效果如下:
從此例中,可以明了感知,每個(gè)模塊都有單獨(dú)的命名空間,避免發(fā)生一些例如變量、函數(shù)命名上的沖突。
推薦閱讀:文章來源:http://www.zghlxwxcb.cn/news/detail-492782.html
t???????Python behind the scenes #11: how the Python import system works (tenthousandmeters.com)https://tenthousandmeters.com/blog/python-behind-the-scenes-11-how-the-python-import-system-works/文章來源地址http://www.zghlxwxcb.cn/news/detail-492782.html
到了這里,關(guān)于Python的模塊(module)和包(package)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!