importlibimport 的實現

3.1 版本新增。

原始碼: Lib/importlib/__init__.py


簡介

importlib 包的目的是三重的。

一是提供 Python 原始碼中 import 語句(以及擴充套件的 __import__() 函式)的實現。這提供了可移植到任何 Python 直譯器的 import 實現。這也提供了一個比用 Python 以外的程式語言實現的更容易理解的實現。

二是,實現 import 的元件在此包中公開,使使用者更容易建立自己的自定義物件(統稱為 匯入器)參與匯入過程。

三是,該軟體包包含用於管理 Python 包的其他功能模組

另請參閱

import 語句

關於 import 語句的語言參考。

包規範

包的原始規範。 自編寫本文件以來,某些語義已更改(例如,根據 sys.modules 中的 None 重定向)。

__import__() 函式

import 語句是此函式的語法糖。

sys.path 模組搜尋路徑的初始化

sys.path 的初始化。

PEP 235

在不區分大小寫的平臺上匯入

PEP 263

定義 Python 原始碼編碼

PEP 302

新的匯入鉤子

PEP 328

匯入:多行和絕對/相對

PEP 366

主模組顯式相對匯入

PEP 420

隱式名稱空間包

PEP 451

匯入系統的 ModuleSpec 型別

PEP 488

消除 PYO 檔案

PEP 489

多階段擴充套件模組初始化

PEP 552

確定性的 pycs

PEP 3120

使用 UTF-8 作為預設原始碼編碼

PEP 3147

PYC 儲存庫目錄

函式

importlib.__import__(name, globals=None, locals=None, fromlist=(), level=0)

內建 __import__() 函式的實現。

注意

模組的程式化匯入應使用 import_module() 而不是此函式。

importlib.import_module(name, package=None)

匯入一個模組。name 引數指定要以絕對或相對方式匯入的模組(例如,pkg.mod..mod)。如果名稱以相對方式指定,則 package 引數必須設定為要用作解析包名錨點的包的名稱(例如,import_module('..mod', 'pkg.subpkg') 將匯入 pkg.mod)。

import_module() 函式充當 importlib.__import__() 的簡化包裝器。這意味著該函式的所有語義都源自 importlib.__import__()。這兩個函式之間最重要的區別是 import_module() 返回指定的包或模組(例如,pkg.mod),而 __import__() 返回頂層包或模組(例如,pkg)。

如果您正在動態匯入自直譯器開始執行以來建立的模組(例如,建立了一個 Python 原始檔),您可能需要呼叫 invalidate_caches(),以便匯入系統注意到新模組。

在 3.3 版本中更改: 父包會自動匯入。

importlib.invalidate_caches()

使儲存在 sys.meta_path 中的查詢器的內部快取失效。如果查詢器實現了 invalidate_caches(),則將呼叫它來執行失效操作。如果在程式執行時建立/安裝了任何模組,則應呼叫此函式以確保所有查詢器都會注意到新模組的存在。

在 3.3 版本中新增。

在 3.10 版本中更改: 在同一名稱空間已被匯入後,在不同的 sys.path 位置建立/安裝的名稱空間包也會被注意到。

importlib.reload(module)

重新載入之前匯入的 module。引數必須是模組物件,因此它必須之前已成功匯入。如果您使用外部編輯器編輯了模組原始檔,並希望在不離開 Python 直譯器的情況下試用新版本,這將非常有用。返回值是模組物件(如果重新匯入導致將不同的物件放入 sys.modules 中,則該物件可能會有所不同)。

reload() 執行時

  • Python 模組的程式碼會被重新編譯,並且會重新執行模組級別的程式碼,從而透過重用最初載入模組的 載入器 來定義一組新的物件,這些物件會繫結到模組字典中的名稱。擴充套件模組的 init 函式不會被第二次呼叫。

  • 與 Python 中的所有其他物件一樣,舊物件僅在其引用計數降至零後才會被回收。

  • 模組名稱空間中的名稱會被更新以指向任何新的或更改的物件。

  • 對舊物件的其他引用(例如,模組外部的名稱)不會重新繫結以引用新物件,如果需要,必須在它們出現的每個名稱空間中更新它們。

還有一些其他注意事項

重新載入模組時,它的字典(包含模組的全域性變數)會被保留。名稱的重新定義會覆蓋舊的定義,所以這通常不是問題。如果模組的新版本沒有定義舊版本定義的名稱,則舊的定義仍然存在。如果模組維護一個全域性表或物件快取,則可以使用此功能 — 透過一個 try 語句,它可以測試該表的存在,並在需要時跳過其初始化

try:
    cache
except NameError:
    cache = {}

重新載入內建模組或動態載入的模組通常不是很有用。不建議重新載入 sys__main__builtins 和其他關鍵模組。在許多情況下,擴充套件模組的設計目的不是被初始化多次,並且在重新載入時可能會以任意方式失敗。

如果一個模組使用 fromimport … 從另一個模組匯入物件,則為其他模組呼叫 reload() 不會重新定義從中匯入的物件 — 一種解決方法是重新執行 from 語句,另一種方法是使用 import 和限定名稱 (module.name) 來代替。

如果一個模組例項化了一個類的例項,則重新載入定義該類的模組不會影響例項的方法定義 — 它們將繼續使用舊的類定義。派生類也是如此。

在 3.4 版本中新增。

在 3.7 版本中更改: 當重新載入的模組缺少 ModuleSpec 時,會引發 ModuleNotFoundError

importlib.abc – 與匯入相關的抽象基類

原始碼: Lib/importlib/abc.py


importlib.abc 模組包含 import 使用的所有核心抽象基類。還提供了一些核心抽象基類的子類,以幫助實現核心 ABC。

ABC 層次結構

object
 +-- MetaPathFinder
 +-- PathEntryFinder
 +-- Loader
      +-- ResourceLoader --------+
      +-- InspectLoader          |
           +-- ExecutionLoader --+
                                 +-- FileLoader
                                 +-- SourceLoader
class importlib.abc.MetaPathFinder

表示 元路徑查詢器 的抽象基類。

在 3.3 版本中新增。

在 3.10 版本中更改: 不再是 Finder 的子類。

find_spec(fullname, path, target=None)

一個用於查詢指定模組的 spec 的抽象方法。如果這是一個頂層匯入,path 將為 None。否則,這是一個搜尋子包或模組的操作,並且 path 將是父包的 __path__ 的值。如果找不到 spec,則返回 None。當傳入時,target 是一個模組物件,查詢器可以使用它來更明智地猜測要返回哪個 spec。importlib.util.spec_from_loader() 對於實現具體的 MetaPathFinders 可能很有用。

在 3.4 版本中新增。

invalidate_caches()

一個可選的方法,當被呼叫時,應該使查詢器使用的任何內部快取失效。當使 sys.meta_path 上所有查詢器的快取失效時,由 importlib.invalidate_caches() 使用。

在 3.4 版本中更改: 呼叫時返回 None 而不是 NotImplemented

class importlib.abc.PathEntryFinder

一個表示 路徑入口查詢器 的抽象基類。雖然它與 MetaPathFinder 有一些相似之處,但 PathEntryFinder 僅用於 importlib.machinery.PathFinder 提供的基於路徑的匯入子系統中。

在 3.3 版本中新增。

在 3.10 版本中更改: 不再是 Finder 的子類。

find_spec(fullname, target=None)

一個用於查詢指定模組的 spec 的抽象方法。查詢器將僅在分配給它的 路徑入口 中搜索模組。如果找不到 spec,則返回 None。當傳入時,target 是一個模組物件,查詢器可以使用它來更明智地猜測要返回哪個 spec。importlib.util.spec_from_loader() 對於實現具體的 PathEntryFinders 可能很有用。

在 3.4 版本中新增。

invalidate_caches()

一個可選的方法,當被呼叫時,應該使查詢器使用的任何內部快取失效。當使所有快取的查詢器的快取失效時,由 importlib.machinery.PathFinder.invalidate_caches() 使用。

class importlib.abc.Loader

一個 載入器 的抽象基類。有關載入器的確切定義,請參閱 PEP 302

希望支援資源讀取的載入器應實現 importlib.resources.abc.ResourceReader 指定的 get_resource_reader() 方法。

在 3.7 版本中更改: 引入了可選的 get_resource_reader() 方法。

create_module(spec)

一個返回匯入模組時要使用的模組物件的方法。此方法可以返回 None,表示應進行預設的模組建立語義。

在 3.4 版本中新增。

在 3.6 版本中更改: 當定義了 exec_module() 時,此方法不再是可選的。

exec_module(module)

一個抽象方法,當匯入或重新載入模組時,在模組自己的名稱空間中執行模組。當呼叫 exec_module() 時,模組應該已經初始化。當此方法存在時,必須定義 create_module()

在 3.4 版本中新增。

在 3.6 版本中更改: 還必須定義 create_module()

load_module(fullname)

一個用於載入模組的傳統方法。如果無法載入模組,則會引發 ImportError,否則返回已載入的模組。

如果請求的模組已經存在於 sys.modules 中,則應使用該模組並重新載入。否則,載入器應建立一個新模組,並在任何載入開始之前將其插入到 sys.modules 中,以防止從匯入中發生遞迴。如果載入器插入了一個模組並且載入失敗,則載入器必須從 sys.modules 中刪除它;在載入器開始執行之前已經在 sys.modules 中的模組應該保持不變。

載入器應在模組上設定多個屬性(請注意,某些屬性可以在重新載入模組時更改)

exec_module() 可用時,將提供向後相容的功能。

在 3.4 版本中更改: 當呼叫時,引發 ImportError 而不是 NotImplementedError。當 exec_module() 可用時,提供功能。

3.4 版本已棄用: 載入模組的推薦 API 是 exec_module() (和 create_module())。載入器應該實現它而不是 load_module()。當實現了 exec_module() 時,匯入機制會處理 load_module() 的所有其他職責。

class importlib.abc.ResourceLoader

一個用於載入器的抽象基類,它實現了可選的 PEP 302 協議,用於從儲存後端載入任意資源。

3.7 版本已棄用: 此 ABC 已被棄用,建議透過 importlib.resources.abc.ResourceReader 支援資源載入。

abstractmethod get_data(path)

一個抽象方法,用於返回位於 *path* 處的資料的位元組。具有允許儲存任意資料的類檔案儲存後端的載入器可以實現此抽象方法,以直接訪問儲存的資料。如果找不到 *path*,則應引發 OSError 。*path* 應該使用模組的 __file__ 屬性或包的 __path__ 中的項來構造。

在 3.4 版本中變更: 引發 OSError 而不是 NotImplementedError

class importlib.abc.InspectLoader

一個用於載入器的抽象基類,它實現了可選的 PEP 302 協議,用於檢查模組的載入器。

get_code(fullname)

返回模組的程式碼物件,如果模組沒有程式碼物件(例如,對於內建模組),則返回 None。如果載入器無法找到請求的模組,則引發 ImportError

注意

雖然該方法具有預設實現,但建議在可能的情況下為了提高效能而重寫它。

在 3.4 版本中變更: 不再是抽象方法,並提供了具體實現。

abstractmethod get_source(fullname)

一個抽象方法,用於返回模組的原始碼。它以文字字串的形式返回,使用 通用換行符,將所有已識別的行分隔符轉換為 '\n' 字元。如果沒有可用的原始碼(例如,內建模組),則返回 None。如果載入器無法找到指定的模組,則引發 ImportError

在 3.4 版本中變更: 引發 ImportError 而不是 NotImplementedError

is_package(fullname)

一個可選方法,如果模組是包,則返回 true 值,否則返回 false 值。如果載入器找不到模組,則引發 ImportError

在 3.4 版本中變更: 引發 ImportError 而不是 NotImplementedError

static source_to_code(data, path='<string>')

從 Python 原始碼建立程式碼物件。

data 引數可以是 compile() 函式支援的任何內容(即字串或位元組)。path 引數應該是原始碼的“路徑”,這可以是一個抽象概念(例如,zip 檔案中的位置)。

使用後續的程式碼物件,可以透過執行 exec(code, module.__dict__) 在模組中執行它。

在 3.4 版本中新增。

在 3.5 版本中變更: 使該方法成為靜態方法。

exec_module(module)

Loader.exec_module() 的實現。

在 3.4 版本中新增。

load_module(fullname)

Loader.load_module() 的實現。

3.4 版本已棄用: 請改用 exec_module()

class importlib.abc.ExecutionLoader

一個繼承自 InspectLoader 的抽象基類,當實現時,有助於將模組作為指令碼執行。該 ABC 表示可選的 PEP 302 協議。

abstractmethod get_filename(fullname)

一個抽象方法,用於返回指定模組的 __file__ 的值。如果沒有可用的路徑,則引發 ImportError

如果有原始碼可用,則無論是否使用位元組碼載入模組,該方法都應返回原始碼檔案的路徑。

在 3.4 版本中變更: 引發 ImportError 而不是 NotImplementedError

class importlib.abc.FileLoader(fullname, path)

一個繼承自 ResourceLoaderExecutionLoader 的抽象基類,提供了 ResourceLoader.get_data()ExecutionLoader.get_filename() 的具體實現。

fullname 引數是載入器要處理的模組的完整解析名稱。path 引數是模組檔案的路徑。

在 3.3 版本中新增。

name

載入器可以處理的模組的名稱。

path

模組檔案的路徑。

load_module(fullname)

呼叫父類的 load_module()

3.4 版本起已棄用: 請改用 Loader.exec_module()

abstractmethod get_filename(fullname)

返回 path

abstractmethod get_data(path)

以二進位制檔案形式讀取 path 並返回其中的位元組。

class importlib.abc.SourceLoader

用於實現原始碼(和可選的位元組碼)檔案載入的抽象基類。該類同時繼承自 ResourceLoaderExecutionLoader,要求實現以下方法:

此類定義的抽象方法用於新增可選的位元組碼檔案支援。不實現這些可選方法(或導致它們引發 NotImplementedError)會導致載入器只能處理原始碼。實現這些方法允許載入器處理原始碼位元組碼檔案;它不允許只提供位元組碼的無原始碼載入。位元組碼檔案是一種最佳化,透過刪除 Python 編譯器的解析步驟來加快載入速度,因此不會公開特定於位元組碼的 API。

path_stats(path)

可選的抽象方法,返回一個包含指定路徑元資料的 dict。支援的字典鍵有:

  • 'mtime'(必需):表示原始碼修改時間的整數或浮點數;

  • 'size'(可選):原始碼的大小(以位元組為單位)。

字典中的任何其他鍵都會被忽略,以便將來進行擴充套件。如果無法處理路徑,則會引發 OSError

在 3.3 版本中新增。

在 3.4 版本中更改: 引發 OSError 而不是 NotImplementedError

path_mtime(path)

可選的抽象方法,返回指定路徑的修改時間。

3.3 版本起已棄用: 此方法已棄用,推薦使用 path_stats()。您不必實現它,但它仍然可用作相容性用途。如果無法處理路徑,則會引發 OSError

在 3.4 版本中更改: 引發 OSError 而不是 NotImplementedError

set_data(path, data)

可選的抽象方法,將指定的位元組寫入檔案路徑。任何不存在的中間目錄都應自動建立。

當由於路徑是隻讀的(errno.EACCES/PermissionError)而導致寫入路徑失敗時,不要傳播異常。

在 3.4 版本中更改: 呼叫時不再引發 NotImplementedError

get_code(fullname)

InspectLoader.get_code() 的具體實現。

exec_module(module)

Loader.exec_module() 的具體實現。

在 3.4 版本中新增。

load_module(fullname)

Loader.load_module() 的具體實現。

3.4 版本起已棄用: 請改用 exec_module()

get_source(fullname)

InspectLoader.get_source() 的具體實現。

is_package(fullname)

InspectLoader.is_package() 的具體實現。如果模組的檔案路徑(由 ExecutionLoader.get_filename() 提供)是一個名為 __init__ 的檔案(當刪除副檔名時),並且模組名稱本身不以 __init__ 結尾,則該模組被確定為包。

class importlib.abc.ResourceReader

已被 TraversableResources 取代

一個 抽象基類,用於提供讀取資源的能力。

從此 ABC 的角度來看,資源 是一個隨包一起提供的二進位制工件。通常,這類似於位於包的 __init__.py 檔案旁的資料檔案。此類旨在幫助抽象出對此類資料檔案的訪問,以便無論包及其資料檔案是儲存在 zip 檔案中還是檔案系統中,都無關緊要。

對於此類的方法,resource 引數應為一個 path-like object,它在概念上僅表示一個檔名。這意味著 resource 引數中不應包含任何子目錄路徑。這是因為讀取器所屬的包的位置充當“目錄”。因此,目錄和檔名的隱喻分別是包和資源。這也是為什麼此類的例項應該直接關聯到特定的包(而不是可能表示多個包或模組)。

希望支援資源讀取的載入器應提供一個名為 get_resource_reader(fullname) 的方法,該方法返回一個實現此 ABC 介面的物件。如果 fullname 指定的模組不是包,則此方法應返回 None。僅當指定的模組是包時,才應返回與此 ABC 相容的物件。

3.7 版本新增。

3.12 版本起已棄用, 將在 3.14 版本中移除: 請改用 importlib.resources.abc.TraversableResources

abstractmethod open_resource(resource)

返回一個已開啟的、用於二進位制讀取 resource類檔案物件

如果找不到資源,則會引發 FileNotFoundError

abstractmethod resource_path(resource)

返回 resource 的檔案系統路徑。

如果資源在檔案系統上不存在,則引發 FileNotFoundError

abstractmethod is_resource(name)

如果命名的 name 被認為是資源,則返回 True。 如果 name 不存在,則會引發 FileNotFoundError

abstractmethod contents()

返回一個包含包內容的字串的可迭代物件。 請注意,迭代器返回的所有名稱不一定是實際的資源,例如,返回 is_resource() 將返回 false 的名稱是可以接受的。

允許返回非資源名稱是為了允許在預先知道包及其資源的儲存方式的情況下,非資源名稱會有用的情況。 例如,允許返回子目錄名稱,這樣當知道包和資源儲存在檔案系統上時,可以直接使用這些子目錄名稱。

抽象方法返回一個不包含任何項的可迭代物件。

class importlib.abc.Traversable

具有 pathlib.Path 方法子集的物件,適用於遍歷目錄和開啟檔案。

對於檔案系統上物件的表示,請使用 importlib.resources.as_file()

3.9 版本新增。

3.12 版本起已棄用, 將在 3.14 版本中移除: 請改用 importlib.resources.abc.Traversable

name

抽象。此物件的基本名稱,不包含任何父引用。

abstractmethod iterdir()

self 中生成 Traversable 物件。

abstractmethod is_dir()

如果 self 是目錄,則返回 True

abstractmethod is_file()

如果 self 是檔案,則返回 True

abstractmethod joinpath(child)

返回 self 中的 Traversable 子項。

abstractmethod __truediv__(child)

返回 self 中的 Traversable 子項。

abstractmethod open(mode='r', *args, **kwargs)

mode 可以是 ‘r’ 或 ‘rb’,分別以文字或二進位制模式開啟。返回適合讀取的控制代碼(與 pathlib.Path.open 相同)。

當以文字模式開啟時,接受編碼引數,如 io.TextIOWrapper 接受的引數。

read_bytes()

以位元組形式讀取 self 的內容。

read_text(encoding=None)

以文字形式讀取 self 的內容。

class importlib.abc.TraversableResources

用於資源讀取器的抽象基類,能夠服務於 importlib.resources.files() 介面。 子類 importlib.resources.abc.ResourceReader 並提供 importlib.resources.abc.ResourceReader 抽象方法的具體實現。因此,任何提供 importlib.abc.TraversableResources 的載入器也提供 ResourceReader。

希望支援資源讀取的載入器應實現此介面。

3.9 版本新增。

3.12 版本起已棄用, 將在 3.14 版本中移除: 請改用 importlib.resources.abc.TraversableResources

abstractmethod files()

返回已載入包的 importlib.resources.abc.Traversable 物件。

importlib.machinery – 匯入器和路徑鉤子

原始碼: Lib/importlib/machinery.py


此模組包含幫助 import 查詢和載入模組的各種物件。

importlib.machinery.SOURCE_SUFFIXES

一個字串列表,表示源模組的可識別檔案字尾。

在 3.3 版本中新增。

importlib.machinery.DEBUG_BYTECODE_SUFFIXES

一個字串列表,表示非最佳化位元組碼模組的檔案字尾。

在 3.3 版本中新增。

3.5 版本起已棄用: 請改用 BYTECODE_SUFFIXES

importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES

一個字串列表,表示最佳化位元組碼模組的檔案字尾。

在 3.3 版本中新增。

3.5 版本起已棄用: 請改用 BYTECODE_SUFFIXES

importlib.machinery.BYTECODE_SUFFIXES

一個字串列表,表示位元組碼模組的可識別檔案字尾(包括前導點)。

在 3.3 版本中新增。

在 3.5 版本中變更: 該值不再依賴於 __debug__

importlib.machinery.EXTENSION_SUFFIXES

一個字串列表,表示擴充套件模組的可識別檔案字尾。

在 3.3 版本中新增。

importlib.machinery.all_suffixes()

返回一個字串組合列表,表示標準匯入機制識別的所有模組的檔案字尾。這對於只需要知道檔案系統路徑是否可能指向模組而不需要任何模組型別詳細資訊的程式碼很有用(例如,inspect.getmodulename())。

在 3.3 版本中新增。

class importlib.machinery.BuiltinImporter

內建模組的匯入器。所有已知的內建模組都列在 sys.builtin_module_names 中。此類實現了 importlib.abc.MetaPathFinderimportlib.abc.InspectLoader ABC。

此類僅定義類方法,以減輕例項化的需要。

在 3.5 版本中更改: 作為 PEP 489 的一部分,內建匯入器現在實現了 Loader.create_module()Loader.exec_module()

class importlib.machinery.FrozenImporter

凍結模組的匯入器。此類實現了 importlib.abc.MetaPathFinderimportlib.abc.InspectLoader ABC。

此類僅定義類方法,以減輕例項化的需要。

在 3.4 版本中更改: 增加了 create_module()exec_module() 方法。

class importlib.machinery.WindowsRegistryFinder

在 Windows 登錄檔中宣告的模組的查詢器。此類實現了 importlib.abc.MetaPathFinder ABC。

此類僅定義類方法,以減輕例項化的需要。

在 3.3 版本中新增。

自 3.6 版本起已棄用: 請改用 site 配置。Python 的未來版本可能預設不啟用此查詢器。

class importlib.machinery.PathFinder

查詢器,用於 sys.path 和包 __path__ 屬性。此類實現了 importlib.abc.MetaPathFinder ABC。

此類僅定義類方法,以減輕例項化的需要。

classmethod find_spec(fullname, path=None, target=None)

嘗試在 sys.path 上或如果已定義,則在 path 上查詢由 fullname 指定的模組的規範的類方法。對於搜尋的每個路徑條目,都會檢查 sys.path_importer_cache。如果找到非假物件,則將其用作路徑條目查詢器,以查詢正在搜尋的模組。如果在 sys.path_importer_cache 中找不到任何條目,則會搜尋 sys.path_hooks,以查詢路徑條目的查詢器,如果找到,則將其與正在查詢的模組一起儲存在 sys.path_importer_cache 中。如果始終找不到查詢器,則 None 會同時儲存在快取中並返回。

在 3.4 版本中新增。

在 3.5 版本中更改: 如果當前工作目錄(用空字串表示)不再有效,則會返回 None,但在 sys.path_importer_cache 中不快取任何值。

classmethod invalidate_caches()

sys.path_importer_cache 中儲存的所有定義了此方法的查詢器呼叫 importlib.abc.PathEntryFinder.invalidate_caches()。否則,將刪除 sys.path_importer_cache 中設定為 None 的條目。

在 3.7 版本中更改: 刪除 sys.path_importer_cacheNone 的條目。

在 3.4 版本中更改: 對於 ''(即空字串),使用當前工作目錄呼叫 sys.path_hooks 中的物件。

class importlib.machinery.FileFinder(path, *loader_details)

importlib.abc.PathEntryFinder 的具體實現,它會快取檔案系統的結果。

path 引數是查詢器負責搜尋的目錄。

loader_details 引數是可變數量的 2 項元組,每個元組都包含一個載入器和載入器識別的檔案字尾序列。 載入器應為可呼叫物件,接受模組的名稱和找到的檔案路徑兩個引數。

查詢器會在必要時快取目錄內容,為每個模組搜尋呼叫 stat,以驗證快取未過時。由於快取陳舊性依賴於作業系統檔案系統狀態資訊的粒度,因此存在搜尋模組、建立新檔案,然後搜尋新檔案所代表的模組的潛在競爭條件。如果操作發生得足夠快以適應 stat 呼叫的粒度,則模組搜尋將失敗。為了防止這種情況發生,當動態建立模組時,請確保呼叫 importlib.invalidate_caches()

在 3.3 版本中新增。

path

查詢器將在其中搜索的路徑。

find_spec(fullname, target=None)

嘗試在 path 中查詢處理 fullname 的規範。

在 3.4 版本中新增。

invalidate_caches()

清除內部快取。

classmethod path_hook(*loader_details)

一個類方法,返回一個閉包,用於 sys.path_hooksFileFinder 的例項由閉包返回,該例項直接使用傳遞給閉包的 path 引數,並間接使用 loader_details 引數。

如果閉包的引數不是一個已存在的目錄,則會引發 ImportError 異常。

class importlib.machinery.SourceFileLoader(fullname, path)

透過繼承 importlib.abc.FileLoader 並提供其他方法的一些具體實現,來實現 importlib.abc.SourceLoader 的具體實現。

在 3.3 版本中新增。

name

此載入器將處理的模組的名稱。

path

原始檔的路徑。

is_package(fullname)

如果 path 看起來是一個包,則返回 True

path_stats(path)

importlib.abc.SourceLoader.path_stats() 的具體實現。

set_data(path, data)

importlib.abc.SourceLoader.set_data() 的具體實現。

load_module(name=None)

importlib.abc.Loader.load_module() 的具體實現,其中指定要載入的模組的名稱是可選的。

3.6 版本後已棄用: 請改用 importlib.abc.Loader.exec_module()

class importlib.machinery.SourcelessFileLoader(fullname, path)

importlib.abc.FileLoader 的具體實現,可以匯入位元組碼檔案(即不存在原始碼檔案)。

請注意,直接使用位元組碼檔案(而不是原始碼檔案)會阻止您的模組被所有 Python 實現或更改位元組碼格式的新 Python 版本所使用。

在 3.3 版本中新增。

name

載入器將處理的模組的名稱。

path

位元組碼檔案的路徑。

is_package(fullname)

根據 path 確定模組是否為包。

get_code(fullname)

返回從 path 建立的 name 的程式碼物件。

get_source(fullname)

當使用此載入器時,由於位元組碼檔案沒有原始碼,因此返回 None

load_module(name=None)

importlib.abc.Loader.load_module() 的具體實現,其中指定要載入的模組的名稱是可選的。

3.6 版本後已棄用: 請改用 importlib.abc.Loader.exec_module()

class importlib.machinery.ExtensionFileLoader(fullname, path)

擴充套件模組的 importlib.abc.ExecutionLoader 的具體實現。

fullname 引數指定載入器要支援的模組的名稱。path 引數是擴充套件模組檔案的路徑。

請注意,預設情況下,如果擴充套件模組沒有實現多階段初始化(請參閱 PEP 489),即使它在其他情況下可以成功匯入,在子直譯器中匯入擴充套件模組也會失敗。

在 3.3 版本中新增。

在 3.12 版本中變更: 現在在子直譯器中使用需要多階段初始化。

name

載入器支援的模組的名稱。

path

擴充套件模組的路徑。

create_module(spec)

根據 PEP 489 從給定的規範建立模組物件。

3.5 版本新增。

exec_module(module)

根據 PEP 489 初始化給定的模組物件。

3.5 版本新增。

is_package(fullname)

如果檔案路徑指向包的 __init__ 模組,則基於 EXTENSION_SUFFIXES 返回 True

get_code(fullname)

由於擴充套件模組缺少程式碼物件,因此返回 None

get_source(fullname)

由於擴充套件模組沒有原始碼,因此返回 None

get_filename(fullname)

返回 path

在 3.4 版本中新增。

class importlib.machinery.NamespaceLoader(name, path, path_finder)

名稱空間包的 importlib.abc.InspectLoader 的具體實現。這是私有類的別名,僅為了檢查名稱空間包上的 __loader__ 屬性而公開。

>>> from importlib.machinery import NamespaceLoader
>>> import my_namespace
>>> isinstance(my_namespace.__loader__, NamespaceLoader)
True
>>> import importlib.abc
>>> isinstance(my_namespace.__loader__, importlib.abc.Loader)
True

3.11 版本新增。

class importlib.machinery.ModuleSpec(name, loader, *, origin=None, loader_state=None, is_package=None)

模組的匯入系統相關狀態的規範。這通常作為模組的 __spec__ 屬性公開。 許多這些屬性也直接在模組上可用:例如,module.__spec__.origin == module.__file__。但是請注意,雖然*值*通常是等效的,但它們可能會有所不同,因為兩個物件之間沒有同步。例如,可以在執行時更新模組的 __file__,這不會自動反映在模組的 __spec__.origin 中,反之亦然。

在 3.4 版本中新增。

name

模組的完全限定名稱(請參閱 module.__name__)。 finder 應該始終將此屬性設定為非空字串。

loader

用於載入模組的 載入器(請參閱 module.__loader__)。 finder 應該始終設定此屬性。

origin

載入器 應載入模組的位置(請參閱 module.__file__)。例如,對於從 .py 檔案載入的模組,這是檔名。 finder 應始終將此屬性設定為對 載入器 有意義的值。在不常見的情況下(例如對於名稱空間包),應將其設定為 None

submodule_search_locations

一個(可能為空的)字串 序列,列舉將找到包的子模組的位置(請參閱 module.__path__)。大多數情況下,此列表中只有一個目錄。

finder 應將此屬性設定為序列,即使是空序列,以嚮導入系統指示該模組是一個包。對於非包模組,應將其設定為 None。稍後會自動將其設定為名稱空間包的特殊物件。

loader_state

finder 可以將此屬性設定為一個物件,其中包含載入模組時要使用的其他特定於模組的資料。否則應將其設定為 None

cached

模組程式碼的編譯版本的檔案的檔名(請參閱 module.__cached__)。 finder 應始終設定此屬性,但對於不需要儲存編譯程式碼的模組,該屬性可能為 None

parent

(只讀)模組所在的包的完全限定名稱(對於頂級模組,則為空字串)。請參閱 module.__package__。如果模組是一個包,則這與 name 相同。

has_location

如果規範的 origin 引用可載入的位置,則為 True,否則為 False。此值會影響如何解釋 origin 以及如何填充模組的 __file__

class importlib.machinery.AppleFrameworkLoader(name, path)

importlib.machinery.ExtensionFileLoader 的一個特例,它能夠載入框架格式的擴充套件模組。

為了與 iOS 應用商店相容,iOS 應用中的*所有*二進位制模組都必須是動態庫,包含在具有適當元資料的框架中,並存儲在打包應用的 Frameworks 資料夾中。每個框架只能有一個二進位制檔案,並且框架資料夾之外不能有可執行二進位制檔案。

為了滿足此要求,在 iOS 上執行時,擴充套件模組二進位制檔案*不*打包為 sys.path 上的 .so 檔案,而是打包為獨立的框架。為了發現這些框架,此載入器將針對 .fwork 副檔名進行註冊,.fwork 檔案充當 sys.path 上二進位制檔案的原始位置的佔位符。.fwork 檔案包含 Frameworks 資料夾中實際二進位制檔案的路徑(相對於應用包)。為了允許將框架打包的二進位制檔案解析回原始位置,框架應包含一個 .origin 檔案,其中包含 .fwork 檔案的位置(相對於應用包)。

例如,考慮匯入 from foo.bar import _whiz 的情況,其中 _whiz 是使用二進位制模組 sources/foo/bar/_whiz.abi3.so 實現的,其中 sources 是註冊在 sys.path 上的位置(相對於應用程式包)。此模組*必須*作為 Frameworks/foo.bar._whiz.framework/foo.bar._whiz 分發(從模組的完整匯入路徑建立框架名稱),在 .framework 目錄中包含一個 Info.plist 檔案,用於將二進位制檔案標識為框架。foo.bar._whiz 模組在原始位置用 sources/foo/bar/_whiz.abi3.fwork 標記檔案表示,其中包含路徑 Frameworks/foo.bar._whiz/foo.bar._whiz。框架還將包含 Frameworks/foo.bar._whiz.framework/foo.bar._whiz.origin,其中包含 .fwork 檔案的路徑。

當使用此載入器載入模組時,模組的 __file__ 將報告為 .fwork 檔案的位置。這允許程式碼使用模組的 __file__ 作為檔案系統遍歷的錨點。但是,規範的來源將引用 .framework 資料夾中*實際*二進位制檔案的位置。

構建應用的 Xcode 專案負責將 PYTHONPATH 中存在的任何 .so 檔案轉換為 Frameworks 資料夾中的框架(包括從模組檔案中刪除副檔名,新增框架元資料,以及簽名生成的框架),並建立 .fwork.origin 檔案。這通常會在 Xcode 專案中使用構建步驟來完成;有關如何構造此構建步驟的詳細資訊,請參閱 iOS 文件。

在 3.13 版本中新增。

可用性:iOS。

name

載入器支援的模組的名稱。

path

擴充套件模組的 .fwork 檔案的路徑。

importlib.util – 匯入器的實用程式碼

原始碼: Lib/importlib/util.py


此模組包含有助於構建匯入器的各種物件。

importlib.util.MAGIC_NUMBER

表示位元組碼版本號的位元組。如果您需要載入/寫入位元組碼方面的幫助,請考慮使用 importlib.abc.SourceLoader

在 3.4 版本中新增。

importlib.util.cache_from_source(path, debug_override=None, *, optimization=None)

返回與源 path 關聯的位元組編譯檔案的 PEP 3147/PEP 488 路徑。例如,如果 path/foo/bar/baz.py,則返回值對於 Python 3.2 將為 /foo/bar/__pycache__/baz.cpython-32.pyccpython-32 字串來自當前魔術標記 (請參閱 get_tag();如果未定義 sys.implementation.cache_tag,則將引發 NotImplementedError)。

optimization 引數用於指定位元組碼檔案的最佳化級別。空字串表示不進行最佳化,因此,optimization''/foo/bar/baz.py 將導致位元組碼路徑為 /foo/bar/__pycache__/baz.cpython-32.pycNone 會導致使用直譯器的最佳化級別。將使用任何其他值的字串表示形式,因此,optimization2/foo/bar/baz.py 將導致位元組碼路徑為 /foo/bar/__pycache__/baz.cpython-32.opt-2.pycoptimization 的字串表示形式只能是字母數字,否則將引發 ValueError

debug_override 引數已棄用,可用於覆蓋系統的 __debug__ 值。True 值等效於將 optimization 設定為空字串。False 值與將 optimization 設定為 1 相同。如果 debug_overrideoptimization 都不為 None,則會引發 TypeError

在 3.4 版本中新增。

在 3.5 版本中更改: 添加了 optimization 引數,並棄用了 debug_override 引數。

在 3.6 版本中更改: 接受路徑類物件

importlib.util.source_from_cache(path)

給定 PEP 3147 檔名的 path,返回關聯的原始碼檔案路徑。例如,如果 path/foo/bar/__pycache__/baz.cpython-32.pyc,則返回的路徑將為 /foo/bar/baz.pypath 不需要存在,但是如果它不符合 PEP 3147PEP 488 格式,則會引發 ValueError。如果未定義 sys.implementation.cache_tag,則會引發 NotImplementedError

在 3.4 版本中新增。

在 3.6 版本中更改: 接受路徑類物件

importlib.util.decode_source(source_bytes)

解碼錶示原始碼的給定位元組,並將其作為具有通用換行符的字串返回 (根據 importlib.abc.InspectLoader.get_source() 的要求)。

在 3.4 版本中新增。

importlib.util.resolve_name(name, package)

將相對模組名稱解析為絕對名稱。

如果 name 沒有前導點,則直接返回 name。這允許諸如 importlib.util.resolve_name('sys', __spec__.parent) 之類的用法,而無需檢查是否需要 package 引數。

如果 name 是相對模組名稱,但是 package 為假值(例如 None 或空字串),則會引發 ImportError。如果相對名稱將逃脫其包含的包(例如,從 spam 包內請求 ..bacon),也會引發 ImportError

在 3.3 版本中新增。

在 3.9 版本中更改: 為了提高與 import 語句的一致性,對於無效的相對匯入嘗試,引發 ImportError,而不是 ValueError

importlib.util.find_spec(name, package=None)

查詢模組的規範,可以選擇相對於指定的 package 名稱。如果模組在 sys.modules 中,則返回 sys.modules[name].__spec__(除非規範為 None 或未設定,在這種情況下會引發 ValueError)。否則,將使用 sys.meta_path 進行搜尋。如果未找到規範,則返回 None

如果 name 用於子模組(包含點),則會自動匯入父模組。

namepackage 的工作方式與 import_module() 相同。

在 3.4 版本中新增。

在 3.7 版本中更改: 如果 package 實際上不是一個包(即缺少 __path__ 屬性),則引發 ModuleNotFoundError 而不是 AttributeError

importlib.util.module_from_spec(spec)

基於 specspec.loader.create_module 建立一個新模組。

如果 spec.loader.create_module 沒有返回 None,那麼任何預先存在的屬性都不會被重置。此外,如果在訪問 spec 或設定模組屬性時觸發 AttributeError,也不會引發該異常。

與使用 types.ModuleType 建立新模組相比,此函式是首選,因為 spec 用於儘可能多地在模組上設定受匯入控制的屬性。

3.5 版本新增。

importlib.util.spec_from_loader(name, loader, *, origin=None, is_package=None)

一個用於基於載入器建立 ModuleSpec 例項的工廠函式。引數的含義與它們在 ModuleSpec 中的含義相同。該函式使用可用的 載入器 API,例如 InspectLoader.is_package(),來填充 spec 上任何缺失的資訊。

在 3.4 版本中新增。

importlib.util.spec_from_file_location(name, location, *, loader=None, submodule_search_locations=None)

一個用於基於檔案路徑建立 ModuleSpec 例項的工廠函式。缺失的資訊將透過使用載入器 API 並隱含該模組將基於檔案來填充到 spec 中。

在 3.4 版本中新增。

在 3.6 版本中更改: 接受路徑類物件

importlib.util.source_hash(source_bytes)

以位元組形式返回 source_bytes 的雜湊值。基於雜湊的 .pyc 檔案在其頭部嵌入了相應原始檔內容的 source_hash()

3.7 版本新增。

importlib.util._incompatible_extension_module_restrictions(*, disable_check)

一個上下文管理器,可以臨時跳過擴充套件模組的相容性檢查。預設情況下,檢查是啟用的,當在子直譯器中匯入單階段初始化模組時,檢查將失敗。當在具有自己 GIL 的直譯器中匯入不支援每個直譯器 GIL 的多階段初始化模組時,檢查也會失敗。

請注意,此函式旨在適應一種不常見的情況;這種情況很可能會最終消失。很有可能這不是您要尋找的。

您可以透過實現多階段初始化的基本介面 (PEP 489) 並謊報對多個直譯器(或每個直譯器 GIL)的支援來獲得與此函式相同的效果。

警告

使用此函式停用檢查可能會導致意外行為,甚至崩潰。它只應在擴充套件模組開發期間使用。

在 3.12 版本中新增。

class importlib.util.LazyLoader(loader)

一個類,它會延遲模組載入器的執行,直到模組的屬性被訪問為止。

這個類 適用於定義了 exec_module() 的載入器,因為需要控制模組使用的模組型別。出於同樣的原因,載入器的 create_module() 方法必須返回 None 或一個型別,該型別的 __class__ 屬性可以被修改,同時不使用 slots。最後,替換 sys.modules 中放置的物件的模組將無法工作,因為沒有辦法安全地正確替換整個直譯器中的模組引用;如果檢測到此類替換,則會引發 ValueError

注意

對於啟動時間至關重要的專案,此類允許在模組從未使用的情況下潛在地最大限度地減少載入模組的成本。對於啟動時間不重要的專案,由於載入期間建立的錯誤訊息被延遲,從而在上下文之外發生,因此 強烈 不鼓勵使用此類。

3.5 版本新增。

在 3.6 版本中更改: 開始呼叫 create_module(),刪除 importlib.machinery.BuiltinImporterimportlib.machinery.ExtensionFileLoader 的相容性警告。

classmethod factory(loader)

一個返回可呼叫物件的類方法,該可呼叫物件建立一個惰性載入器。這旨在用於載入器透過類而不是透過例項傳遞的情況。

suffixes = importlib.machinery.SOURCE_SUFFIXES
loader = importlib.machinery.SourceFileLoader
lazy_loader = importlib.util.LazyLoader.factory(loader)
finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))

示例

以程式設計方式匯入

要以程式設計方式匯入模組,請使用 importlib.import_module()

import importlib

itertools = importlib.import_module('itertools')

檢查是否可以匯入模組

如果您需要找出是否可以匯入模組而不實際執行匯入,那麼您應該使用 importlib.util.find_spec()

請注意,如果 name 是一個子模組(包含點),importlib.util.find_spec() 將匯入父模組。

import importlib.util
import sys

# For illustrative purposes.
name = 'itertools'

if name in sys.modules:
    print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
    # If you chose to perform the actual import ...
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    print(f"{name!r} has been imported")
else:
    print(f"can't find the {name!r} module")

直接匯入原始檔

應謹慎使用此方法:它是匯入語句的近似表示,其中直接指定檔案路徑,而不是搜尋 sys.path。應首先考慮替代方法,例如在需要正確的模組時修改 sys.path,或者在執行 Python 檔案產生的全域性名稱空間合適時使用 runpy.run_path()

要直接從路徑匯入 Python 原始檔,請使用以下方法

import importlib.util
import sys


def import_from_path(module_name, file_path):
    spec = importlib.util.spec_from_file_location(module_name, file_path)
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    return module


# For illustrative purposes only (use of `json` is arbitrary).
import json
file_path = json.__file__
module_name = json.__name__

# Similar outcome as `import json`.
json = import_from_path(module_name, file_path)

實現惰性匯入

下面的示例展示瞭如何實現惰性匯入

>>> import importlib.util
>>> import sys
>>> def lazy_import(name):
...     spec = importlib.util.find_spec(name)
...     loader = importlib.util.LazyLoader(spec.loader)
...     spec.loader = loader
...     module = importlib.util.module_from_spec(spec)
...     sys.modules[name] = module
...     loader.exec_module(module)
...     return module
...
>>> lazy_typing = lazy_import("typing")
>>> #lazy_typing is a real module object,
>>> #but it is not loaded in memory yet.
>>> lazy_typing.TYPE_CHECKING
False

設定匯入器

對於匯入的深度自定義,您通常希望實現一個 匯入器。這意味著管理 查詢器載入器 兩方面。對於查詢器,根據您的需要有兩種選擇:元路徑查詢器路徑條目查詢器。前者是您放在 sys.meta_path 上的,而後者是您使用 路徑條目鉤子sys.path_hooks 上建立的,它與 sys.path 條目一起工作,以潛在地建立查詢器。此示例將向您展示如何註冊自己的匯入器,以便匯入將使用它們(有關為您自己建立匯入器的資訊,請閱讀此包中定義的相應類的文件)

import importlib.machinery
import sys

# For illustrative purposes only.
SpamMetaPathFinder = importlib.machinery.PathFinder
SpamPathEntryFinder = importlib.machinery.FileFinder
loader_details = (importlib.machinery.SourceFileLoader,
                  importlib.machinery.SOURCE_SUFFIXES)

# Setting up a meta path finder.
# Make sure to put the finder in the proper location in the list in terms of
# priority.
sys.meta_path.append(SpamMetaPathFinder)

# Setting up a path entry finder.
# Make sure to put the path hook in the proper location in the list in terms
# of priority.
sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))

近似 importlib.import_module()

匯入本身是用 Python 程式碼實現的,這使得可以透過 importlib 公開大部分匯入機制。以下透過提供 importlib.import_module() 的近似實現,來幫助說明 importlib 公開的各種 API。

import importlib.util
import sys

def import_module(name, package=None):
    """An approximate implementation of import."""
    absolute_name = importlib.util.resolve_name(name, package)
    try:
        return sys.modules[absolute_name]
    except KeyError:
        pass

    path = None
    if '.' in absolute_name:
        parent_name, _, child_name = absolute_name.rpartition('.')
        parent_module = import_module(parent_name)
        path = parent_module.__spec__.submodule_search_locations
    for finder in sys.meta_path:
        spec = finder.find_spec(absolute_name, path)
        if spec is not None:
            break
    else:
        msg = f'No module named {absolute_name!r}'
        raise ModuleNotFoundError(msg, name=absolute_name)
    module = importlib.util.module_from_spec(spec)
    sys.modules[absolute_name] = module
    spec.loader.exec_module(module)
    if path is not None:
        setattr(parent_module, child_name, module)
    return module