Python 模組元路徑尋找器介紹
先決條件
閱讀本節的先決條件是對 Python 模組尋找器有所掌握,你可以檢視Python 模組尋找器介紹一節來了解相關資訊。
Python 模組元路徑尋找器
Python 模組元路徑尋找器(Module Meta Path Finder)預設可以完成以下幾項工作,尋找內建模組,尋找凍結模組,尋找基於路徑的模組。
事實上,元路徑尋找器是真正意義上的 Python 模組尋找器,在尋找定位模組的過程中,所有元路徑尋找器被依次調,當某個元路徑尋找器找到模組時,將傳回一個描述該模組的物件(整個尋找過程結束),否則,將傳回None
。當所有元路徑尋找器均傳回None
時,說明模組無法被定位,這將引發例外狀況ModuleNotFoundError
。
檢視 Python 模組元路徑尋找器
元路徑尋找器儲存在sys
模組的meta_path
變數中,你可以在 Python 的互動模式中,輸入import sys
和sys.meta_path
兩行程式碼,來檢視目前的元路徑尋找器。如果是py
檔案,則可以改寫sys.meta_path
為print(sys.meta_path)
。
import sys
sys.meta_path
[<_distutils_hack.DistutilsMetaFinder object at…>, <class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>]
# 顯示元路徑尋找器
import sys
print(sys.meta_path)
尋找 Python 內建和凍結模組
元路徑尋找器 BuiltinImporter 和 FrozenImporter,分別用於尋找 Python 的內建和凍結模組。當然,在 Python 啟動時,一些內建或凍結模組會自動匯入,並儲存在sys.modules
中,他們再次被 BuiltinImporter 或 FrozenImporter 匯入的可能性不大,除非對應的快取被清除。
廣義上的 Python “內建模組”可以是凍結模組
如果你將 Python 啟動後sys.modules
中包含的模組稱為“內建模組”,那麽“內建模組”可以是凍結模組,基於路徑載入的模組,或真正意義上的內建(built-in)模組。比如,廣義上的“內建模組”os
是一個凍結模組,廣義上的“內建模組”sys
是一個真正的內建(built-in)模組。
請註意,以上這些情況可能因為 Python 版本的不同而有所變化。
模組
要了解模組快取,你可以檢視Python 模組快取一段。
在互動模式中,我們匯入模組os
,使用globals()
函式檢視全域資訊,發現匯入的模組os
是一個凍結模組。刪除凍結模組尋找器 FrozenImporter 以及模組os
在sys.modules
中的快取,再次執行import os
和globals()
,發現模組os
不再是凍結模組。這是因為 FrozenImporter 尋找器被刪除,os
是通過其他尋找器被定位的。
import os
globals()
{…'os': <module 'os' (frozen)>}
import sys
sys.meta_path
[<_distutils_hack.DistutilsMetaFinder object at…>, <class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>]
del sys.meta_path[2]
del sys.modules['os']
import os
globals()
{…'os': <module 'os' from '…'>,…}
為何有些 Python 模組元路徑尋找器的類別名稱包含英文單詞 Importer?
BuiltinImporter 和 FrozenImporter 的準確翻譯,應該是內建匯入器和凍結匯入器,但由於匯入器同時具有尋找器和載入器的功能,因此,也可以稱他們為尋找器。
尋找基於路徑的 Python 模組
元路徑尋找器 PathFinder,也被稱為基於路徑尋找器,用於尋找基於模組搜尋路徑的 Python 模組,這大概是最為常見的情況,當你希望匯入第三方或自己編寫的模組或套件時, PathFinder 將開始工作。
廣義上的 Python “內建模組”可以是基於路徑載入的模組
通過查詢sys.modules
可以發現,在“內建模組”中,有不少是通過基於路徑尋找器來定位的。
實作 Python 基於路徑尋找器的可拓展性
Python 模組尋找器的另一分類,路徑項目尋找器,是基於路徑尋找器的具體實作,因此,可以通過編寫路徑項目尋找器,拓展基於路徑尋找器的功能。比如,定位在網路上儲存的 Python 腳本。
模組搜尋路徑
要了解模組搜尋路徑,你可以檢視Python 模組搜尋路徑介紹,Python 模組搜尋路徑中的目錄有哪些一節。
Python 模組元路徑尋找器的優先順序
如前所述,在尋找模組時,元路徑尋找器是被依次呼叫的,如果他們在sys.meta_path
中的順序被改變,那麽可能會引發意想不到的問題。
下面,我們編寫了一個自己的os
模組,將命令列切換至該模組所在的目錄,然後進入 Python 互動模式,把優先順序較低的 PathFinder 尋找器放到串列sys.meta_path
的首位,清除os
模組的快取並重新匯入,優先順序最高的 PathFinder 將找到我們編寫的os
模組。
print('我不是那個 os 模組!')
import sys
sys.meta_path
[<_distutils_hack.DistutilsMetaFinder object at…>, <class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>]
sys.meta_path.reverse()
del sys.modules['os']
import os
我不是那個 os 模組!
程式碼
print_meta_path.py·codebeatme/python-reference·GitHub
os.py·codebeatme/python-reference·GitHub