Python 模組元路徑尋找器介紹

閱讀 5:49·字數 1750·發佈 
Youtube 頻道
訂閱 133

先決條件

閱讀本節的先決條件是對 Python 模組尋找器有所掌握,你可以檢視Python 模組尋找器介紹一節來了解相關資訊。

Python 模組元路徑尋找器

Python 模組元路徑尋找器(Module Meta Path Finder)預設可以完成以下幾項工作,尋找內建模組,尋找凍結模組,尋找基於路徑的模組。

事實上,元路徑尋找器是真正意義上的 Python 模組尋找器,在尋找定位模組的過程中,所有元路徑尋找器被依次調,當某個元路徑尋找器找到模組時,將傳回一個描述該模組的物件(整個尋找過程結束),否則,將傳回None。當所有元路徑尋找器均傳回None時,說明模組無法被定位,這將引發例外狀況ModuleNotFoundError

檢視 Python 模組元路徑尋找器

元路徑尋找器儲存在sys模組的meta_path變數中,你可以在 Python 的互動模式中,輸入import syssys.meta_path兩行程式碼,來檢視目前的元路徑尋找器。如果是py檔案,則可以改寫sys.meta_pathprint(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'>]
print_meta_path.py
# 顯示元路徑尋找器
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 以及模組ossys.modules中的快取,再次執行import osglobals(),發現模組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模組。

os.py
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