Python學習入門(17)—模塊(一)

(本號正在連續推出以Python官網文檔為主線的系統學習Python的系列文章或視頻,感興趣的朋友們歡迎點擊關注。在這裡學習Python事半功倍!本文及後續文章如無特別聲明均以Windows平臺作為演示平臺,Python版本為:3.8.1)


之前的文章中我們一直使用交互方式進行演示,但當退出Python解釋器再次進入後會發現之前所有的定義全部丟失了。因此除非有交互需求或執行簡短的臨時性操作,在實際中更多使用的腳步運行方式(這種運行方式在之前的文中已經介紹過,參閱Python學習入門(7)—開始編程)。在實際程序開發中,隨著程序變得越來越長,為了更好的維護性,需要將較長的腳本文件分成較小的幾個文件,並且為了提高開發效率需要複用這些文件中的定義。為了支持這一點,Python提供了一種在一個腳本文件中定義在其他腳本或解釋器的交互式模式中使用這些定義的方法。這樣的包含定義的腳本文件稱為模塊,模塊中的定義可以導入到其他模塊或主模塊中(在頂層執行的腳本和計算器模式中可以訪問的變量集合)。

模塊的創建

創建模塊其實就是創建一個擴展名為.py的腳本文件,其中包含需要作的定義(變量定義,函數定義,類定義等)。可以使用任何文本編輯器編輯此腳本文件,由於Python解釋器默認是按UTF-8的編碼格式解析腳本文件的,建議大家將腳本文件保存為UTF-8編碼格式。如果腳本文件不是使用的UTF-8編碼格式,則需要在文件開始處作形如# -*- coding: encoding -*-的聲明,其中encoding表示所使用的編碼格式。示例如下:

Python學習入門(17)—模塊(一)

【示例】模塊定義

【注】在實例中創建了模塊fib.py並在其中定義了兩個函數fib1和fib2,分別用於輸出和返回Fibonacci數列。除此之外,還在末尾增加了if語句塊,這段代碼在模塊作為腳本運行時才會被執行。

模塊的導入及使用

在Python中必須使用import命令先導入模塊後才能使用。import命令有以下幾種形式:

  • importm [as mm] 導入模塊m,指定導入後的名字為mm。其中指定導入模塊的別名是可選的。
  • from m importf1 [asff1],[f2 [as ff2]] 從模塊中導入f1和f2,分別指定導入後名字為ff1和ff2。從模塊中可以導入多個名字,其中指定導入模塊的別名是可選的。
  • from m import* 從模塊中導入除以下劃線_開始的所有名字。注意:一般來說,從模塊或包中導入*的做法不是一種好的做法,因為它通常會導致代碼的可讀性變差。但是,在交互運行模式中使用它來減少輸入工作量還是可行的。

直接包含在模塊中的可執行語句,在模塊導入時會被執行,如示例模塊中的print("這是定義了Fibonacci數列函數的模塊")語句。實際開發中一般使用這樣的語句來執行模塊初始化工作。

示例如下:

Python學習入門(17)—模塊(一)

【示例】模塊的導入及使用

【注】為了提高效率,每個模塊在每個解釋器會話中只導入一次。因此,如果模塊發生了改變,就必須重新啟動解釋器後重新導入該模塊,或者如果只是一個模塊你想要交互測試,可使用import importlib;importlib.reload (modulename)命令來重新導入(不需要重啟解釋器)。

模塊作為腳本運行

如果模塊中有if __name__=="__main__":語句塊,則以腳本形式運行模塊時會執行該語句塊中語句。而導入模塊時這些語句是不被執行的。示例如下:

Python學習入門(17)—模塊(一)

【示例】模塊作為腳本運行

【注】模塊中使用if __name__=="__main__":語句塊通常用於為模塊提供方便的用戶界面,或者用於測試目的(將模塊作為腳本運行以執行測試套件)。

模塊的搜索路徑

當導入名為fib的模塊時,解釋器首先搜索具有該名稱的內置模塊。如果沒有找到,它將在變量sys.path提供的目錄列表中搜索名為fib.py的文件,如果沒搜索到則報錯。sys.path是由下面的位置初始化的:

包含輸入腳本的目錄(或未指定文件時的當前目錄)。環境變量PYTHONPATH。該環境變量包含以;分割的目錄名,語法與環境變量PATH相同。安裝時設置的默認值。值得注意的是:初始化之後,Python會修改sys.path,將正在運行的腳本的目錄置於搜索路徑的開頭(在標準庫路徑之前)。這意味著當加載某一模塊時該目錄中模塊會優先於庫目錄中的同名模塊。如果這不是想要的,就會產生難以調試的錯誤。

【注】在支持符號鏈接的文件系統中,腳本所在的包含符號鏈接的目錄會被轉換成實際目錄後才會添加到模塊搜索路徑中。

已編譯的Python文件

為了提升加載模塊的速度,Python在目錄_pycache__下將每個模塊緩存為名為moduleName.version.pyc形式的編譯文件,其中,moduleName為模塊名,version為已編譯文件的格式,通常為Python編譯器名-版本號的形式。例如,在CPython 3.3版本中,m.py的已編譯版本將被緩存為名為_pycache__/m.cpython-33.pyc的文件。這種命名約定允許來自不同版本的已編譯模塊一起共存。

Python通過對比已編譯模塊文件和源文件的修改日期來決定已編譯模塊文件是否已經過期,如果已編譯模塊文件的修改日期較早說明已過期需要重新編譯。這是一個完全自動的過程。此外,已編譯模塊是平臺獨立的,因此可以在具有不同體系結構的系統之間共享相同的庫。

Python在兩種情況下不檢查緩存。首先,對於直接從命令行加載的模塊它總是重新編譯並且不存儲結果。其次,如果沒有源模塊,它不會檢查緩存。要支持非源(僅編譯)發行版,已編譯模塊必須位於源目錄中,且不能有源模塊。

在運行Python命令時如果使用了-O或-OO開關則可以減少已編譯模塊的大小。使用-O開關會刪除assert語句,使用-OO開關會同時刪除assert語句和_doc__字符串。由於一些程序可能依賴於這些功能,所以在確定不需要這些功能時再使用這些選項。優化了的模塊會有一個opt標籤,並且通常佔用比較小的空間。未來的版本可能會改變優化的效果。

需要說明的是:從.pyc文件中讀取程序並不比從.py文件中讀取快,.pyc文件唯一的優勢是加載速度較快。

如果需要為某個目錄下的所有模塊創建已編譯模塊(.pyc文件),則可以使用compileall模塊提供的方法。具體使用方法在後續文章中會介紹。

[關於"模塊"部分的內容本篇未完,下篇將繼續講解]

【結束】


分享到:


相關文章: