importlib --- import 的實現(xiàn)?
3.1 新版功能.
概述?
importlib 包的目的有兩個。 第一個目的是在 Python 源代碼中提供 import 語句的實現(xiàn)(并且因此而擴(kuò)展 __import__() 函數(shù))。 這提供了一個可移植到任何 Python 解釋器的 import 實現(xiàn)。 相比使用 Python 以外的編程語言實現(xiàn)方式,這一實現(xiàn)更加易于理解。
第二個目的是實現(xiàn) import 的部分被公開在這個包中,使得用戶更容易創(chuàng)建他們自己的自定義對象 (通常被稱為 importer) 來參與到導(dǎo)入過程中。
參見
- import 語句
import語句的語言參考- 包規(guī)格說明
包的初始規(guī)范。自從編寫這個文檔開始,一些語義已經(jīng)發(fā)生改變了(比如基于
sys.modules中None的重定向)。__import__()函數(shù)import語句是這個函數(shù)的語法糖。- PEP 235
在忽略大小寫的平臺上進(jìn)行導(dǎo)入
- PEP 263
定義 Python 源代碼編碼
- PEP 302
新導(dǎo)入鉤子
- PEP 328
導(dǎo)入:多行和絕對/相對
- PEP 366
主模塊顯式相對導(dǎo)入
- PEP 420
隱式命名空間包
- PEP 451
導(dǎo)入系統(tǒng)的一個模塊規(guī)范類型
- PEP 488
消除PYO文件
- PEP 489
多階段擴(kuò)展模塊初始化
- PEP 552
確定性的 pyc 文件
- PEP 3120
使用 UTF-8 作為默認(rèn)的源編碼
- PEP 3147
PYC 倉庫目錄
函數(shù)?
-
importlib.__import__(name, globals=None, locals=None, fromlist=(), level=0)? 內(nèi)置
__import__()函數(shù)的實現(xiàn)。注解
程序式地導(dǎo)入模塊應(yīng)該使用
import_module()而不是這個函數(shù)。
-
importlib.import_module(name, package=None)? 導(dǎo)入一個模塊。參數(shù) name 指定了以絕對或相對導(dǎo)入方式導(dǎo)入什么模塊 (比如要么像這樣
pkg.mod或者這樣..mod)。如果參數(shù) name 使用相對導(dǎo)入的方式來指定,那么那個參數(shù) packages 必須設(shè)置為那個包名,這個包名作為解析這個包名的錨點 (比如import_module('..mod', 'pkg.subpkg')將會導(dǎo)入pkg.mod)。import_module()函數(shù)是一個對importlib.__import__()進(jìn)行簡化的包裝器。 這意味著該函數(shù)的所有主義都來自于importlib.__import__()。 這兩個函數(shù)之間最重要的不同點在于import_module()返回指定的包或模塊 (例如pkg.mod),而__import__()返回最高層級的包或模塊 (例如pkg)。如果動態(tài)導(dǎo)入一個自從解釋器開始執(zhí)行以來被創(chuàng)建的模塊(即創(chuàng)建了一個 Python 源代碼文件),為了讓導(dǎo)入系統(tǒng)知道這個新模塊,可能需要調(diào)用
invalidate_caches()。在 3.3 版更改: 父包會被自動導(dǎo)入。
-
importlib.find_loader(name, path=None)? 查找一個模塊的加載器,可選擇地在指定的 path 里面。如果這個模塊是在
sys.modules,那么返回sys.modules[name].__loader__(除非這個加載器是None或者是沒有被設(shè)置, 在這樣的情況下,會引起ValueError異常)。 否則使用sys.meta_path的一次搜索就結(jié)束。如果未發(fā)現(xiàn)加載器,則返回None。點狀的名稱沒有使得它父包或模塊隱式地導(dǎo)入,因為它需要加載它們并且可能不需要。為了適當(dāng)?shù)貙?dǎo)入一個子模塊,需要導(dǎo)入子模塊的所有父包并且使用正確的參數(shù)提供給 path。
3.3 新版功能.
在 3.4 版更改: 如果沒有設(shè)置
__loader__,會引起ValueError異常,就像屬性設(shè)置為None的時候一樣。3.4 版后已移除: 使用
importlib.util.find_spec()來代替。
-
importlib.invalidate_caches()? 使查找器存儲在
sys.meta_path中的內(nèi)部緩存無效。如果一個查找器實現(xiàn)了invalidate_caches(),那么它會被調(diào)用來執(zhí)行那個無效過程。 如果創(chuàng)建/安裝任何模塊,同時正在運行的程序是為了保證所有的查找器知道新模塊的存在,那么應(yīng)該調(diào)用這個函數(shù)。3.3 新版功能.
-
importlib.reload(module)? 重新加載之前導(dǎo)入的 module。那個參數(shù)必須是一個模塊對象,所以它之前必須已經(jīng)成功導(dǎo)入了。這樣做是有用的,如果使用外部編輯器編已經(jīng)輯過了那個模塊的源代碼文件并且想在退出 Python 解釋器之前試驗這個新版本的模塊。函數(shù)的返回值是那個模塊對象(如果重新導(dǎo)入導(dǎo)致一個不同的對象放置在
sys.modules中,那么那個模塊對象是有可能會不同)。當(dāng)執(zhí)行
reload()的時候:Python 模塊的代碼會被重新編譯并且那個模塊級的代碼被重新執(zhí)行,通過重新使用一開始加載那個模塊的 loader,定義一個新的綁定在那個模塊字典中的名稱的對象集合。擴(kuò)展模塊的``init``函數(shù)不會被調(diào)用第二次。
與Python中的所有的其它對象一樣,舊的對象只有在它們的引用計數(shù)為0之后才會被回收。
模塊命名空間中的名稱重新指向任何新的或更改后的對象。
其他舊對象的引用(例如那個模塊的外部名稱)不會被重新綁定到引用的新對象的,并且如果有需要,必須在出現(xiàn)的每個命名空間中進(jìn)行更新。
有一些其他注意事項:
當(dāng)一個模塊被重新加載的時候,它的字典(包含了那個模塊的全區(qū)變量)會被保留。名稱的重新定義會覆蓋舊的定義,所以通常來說這不是問題。如果一個新模塊沒有定義在舊版本模塊中定義的名稱,則將保留舊版本中的定義。這一特性可用于作為那個模塊的優(yōu)點,如果它維護(hù)一個全局表或者對象的緩存 —— 使用
try語句,就可以測試表的存在并且跳過它的初始化,如果有需要的話:try: cache except NameError: cache = {}
重新加載內(nèi)置的或者動態(tài)加載模塊,通常來說不是很有用處。不推薦重新加載"
sys,__main__,builtins和其它關(guān)鍵模塊。在很多例子中,擴(kuò)展模塊并不是設(shè)計為不止一次的初始化,并且當(dāng)重新加載時,可能會以任意方式失敗。如果一個模塊使用
from...import... 導(dǎo)入的對象來自另外一個模塊,給其它模塊調(diào)用reload()不會重新定義來自這個模塊的對象 —— 解決這個問題的一種方式是重新執(zhí)行from語句,另一種方式是使用import和限定名稱(module.name)來代替。如果一個模塊創(chuàng)建一個類的實例,重新加載定義那個類的模塊不影響那些實例的方法定義———它們繼續(xù)使用舊類中的定義。對于子類來說同樣是正確的。
3.4 新版功能.
在 3.7 版更改: 當(dāng)重新加載的那個模塊缺少
ModuleSpec的時候,會引起ModuleNotFoundError異常。
importlib.abc —— 關(guān)于導(dǎo)入的抽象基類?
源代碼: Lib/importlib/abc.py
The importlib.abc module contains all of the core abstract base classes
used by import. Some subclasses of the core abstract base classes
are also provided to help in implementing the core ABCs.
ABC 類的層次結(jié)構(gòu):
object
+-- Finder (deprecated)
| +-- MetaPathFinder
| +-- PathEntryFinder
+-- Loader
+-- ResourceLoader --------+
+-- InspectLoader |
+-- ExecutionLoader --+
+-- FileLoader
+-- SourceLoader
-
class
importlib.abc.Finder? 代表 finder 的一個抽象基類
3.3 版后已移除: 使用
MetaPathFinder或PathEntryFinder來代替。-
abstractmethod
find_module(fullname, path=None)? 為指定的模塊查找 loader 定義的抽象方法。本來是在 PEP 302 指定的,這個方法是在
sys.meta_path和基于路徑的導(dǎo)入子系統(tǒng)中使用。在 3.4 版更改: 當(dāng)被調(diào)用的時候,返回
None而不是引發(fā)NotImplementedError。
-
abstractmethod
-
class
importlib.abc.MetaPathFinder? 代表 meta path finder 的一個抽象基類。 為了保持兼容性,這是
Finder的一個子類。3.3 新版功能.
-
find_spec(fullname, path, target=None)? 一個抽象方法,用于查找指定模塊的 spec 。若是頂層導(dǎo)入,path 將為
None。 否則就是查找子包或模塊,path 將是父級包的__path__值。找不到則會返回None。傳入的target是一個模塊對象,查找器可以用來對返回的規(guī)格進(jìn)行更有依據(jù)的猜測。在實現(xiàn)具體的MetaPathFinders代碼時,可能會用到importlib.util.spec_from_loader()。3.4 新版功能.
-
find_module(fullname, path)? 一個用于查找指定的模塊中 loader 的遺留方法。如果這是最高層級的導(dǎo)入,path 的值將會是
None。否則,這是一個查找子包或者模塊的方法,并且 path 的值將會是來自父包的__path__的值。如果未發(fā)現(xiàn)加載器,返回None。如果定義了
find_spec()方法,則提供了向后兼容的功能。在 3.4 版更改: 當(dāng)調(diào)用這個方法的時候返回
None而不是引發(fā)NotImplementedError。 可以使用find_spec()來提供功能。3.4 版后已移除: 使用
find_spec()來代替。
-
invalidate_caches()? 當(dāng)被調(diào)用的時候,一個可選的方法應(yīng)該將查找器使用的任何內(nèi)部緩存進(jìn)行無效。將在
sys.meta_path上的所有查找器的緩存進(jìn)行無效的時候,這個函數(shù)被importlib.invalidate_caches()所使用。在 3.4 版更改: 當(dāng)方法被調(diào)用的時候,方法返回是
None而不是NotImplemented。
-
-
class
importlib.abc.PathEntryFinder? path entry finder 的一個抽象基類。盡管這個基類和
MetaPathFinder有一些相似之處,但是PathEntryFinder只在由PathFinder提供的基于路徑導(dǎo)入子系統(tǒng)中使用。這個抽象類是 Finder 的一個子類,僅僅是因為兼容性的原因。3.3 新版功能.
-
find_spec(fullname, target=None)? 一個抽象方法,用于查找指定模塊的 spec。搜索器將只在指定的 path entry 內(nèi)搜索該模塊。找不到則會返回
None。在實現(xiàn)具體的PathEntryFinders代碼時,可能會用到importlib.util.spec_from_loader()。3.4 新版功能.
-
find_loader(fullname)? 一個用于在模塊中查找一個 loader 的遺留方法。 返回一個
(loader, portion)的2元組,portion是一個貢獻(xiàn)給命名空間包部分的文件系統(tǒng)位置的序列。 加載器可能是None,同時正在指定的portion表示的是貢獻(xiàn)給命名空間包的文件系統(tǒng)位置。portion可以使用一個空列表來表示加載器不是命名空間包的一部分。 如果loader是None并且portion是一個空列表,那么命名空間包中無加載器或者文件系統(tǒng)位置可查找到(即在那個模塊中未能找到任何東西)。如果定義了
find_spec(),則提供了向后兼容的功能。在 3.4 版更改: 返回
(None, [])而不是引發(fā)NotImplementedError。 當(dāng)可于提供相應(yīng)的功能的時候,使用find_spec()。3.4 版后已移除: 使用
find_spec()來代替。
-
find_module(fullname)? Finder.find_module`的具體實現(xiàn),該方法等價于``self.find_loader(fullname)[0]`()。3.4 版后已移除: 使用
find_spec()來代替。
-
invalidate_caches()? 當(dāng)被調(diào)用的時候,一個可選的方法應(yīng)該將查找器使用的任何內(nèi)部緩存進(jìn)行無效。當(dāng)將所有緩存的查找器的緩存進(jìn)行無效的時候,該函數(shù)被
PathFinder.invalidate_caches()使用。
-
-
class
importlib.abc.Loader? loader 的抽象基類。 關(guān)于一個加載器的實際定義請查看 PEP 302。
加載器想要支持資源讀取應(yīng)該實現(xiàn)一個由
importlib.abc.ResourceReader指定的``get_resource_reader(fullname)`` 方法。在 3.7 版更改: 引入了可選的
get_resource_reader()方法。-
create_module(spec)? 當(dāng)導(dǎo)入一個模塊的時候,一個返回將要使用的那個模塊對象的方法。這個方法可能返回
None,這暗示著應(yīng)該發(fā)生默認(rèn)的模塊創(chuàng)建語義。"3.4 新版功能.
在 3.5 版更改: 從 Python 3.6 開始,當(dāng)定義了
exec_module()的時候,這個方法將不會是可選的。
-
exec_module(module)? 當(dāng)一個模塊被導(dǎo)入或重新加載時,一個抽象方法在它自己的命名空間中執(zhí)行那個模塊。當(dāng)調(diào)用
exec_module()的時候,那個模塊應(yīng)該已經(jīng)被初始化 了。當(dāng)這個方法存在時,必須定義create_module()。3.4 新版功能.
在 3.6 版更改:
create_module()也必須被定義。
-
load_module(fullname)? 用于加載一個模塊的傳統(tǒng)方法。如果這個模塊不能被導(dǎo)入,將引起
ImportError異常,否則返回那個被加載的模塊。如果請求的模塊已經(jīng)存在
sys.modules,應(yīng)該使用并且重新加載那個模塊。 否則加載器應(yīng)該是創(chuàng)建一個新的模塊并且在任何家過程開始之前將這個新模塊插入到sys.modules中,來阻止遞歸導(dǎo)入。 如果加載器插入了一個模塊并且加載失敗了,加載器必須從sys.modules中將這個模塊移除。在加載器開始執(zhí)行之前,已經(jīng)在sys.modules中的模塊應(yīng)該被忽略 (查看importlib.util.module_for_loader())。加載器應(yīng)該在模塊上面設(shè)置幾個屬性。(要知道當(dāng)重新加載一個模塊的時候,那些屬性某部分可以改變):
__name__模塊的名字
__file__模塊數(shù)據(jù)存儲的路徑(不是為了內(nèi)置的模塊而設(shè)置)
__cached__被存儲或應(yīng)該被存儲的模塊的編譯版本的路徑(當(dāng)這個屬性不恰當(dāng)?shù)臅r候不設(shè)置)。
__path__指定在一個包中搜索路徑的一個字符串列表。這個屬性不在模塊上面進(jìn)行設(shè)置。
__package__模塊/包的父包。如果這個模塊是最上層的,那么它是一個為空字符串的值。
importlib.util.module_for_loader()裝飾器可以處理__package__的細(xì)節(jié)。
__loader__用來加載那個模塊的加載器。
importlib.util.module_for_loader()裝飾器可以處理__package__的細(xì)節(jié)。
當(dāng)
exec_module()可用的時候,那么則提供了向后兼容的功能。在 3.4 版更改: 當(dāng)這個方法被調(diào)用的時候,觸發(fā)
ImportError異常而不是NotImplementedError。當(dāng)exec_module()可用的時候,使用它的功能。3.4 版后已移除: 加載模塊推薦的使用的 API 是
exec_module()(和create_module())。 加載器應(yīng)該實現(xiàn)它而不是 load_module()。 當(dāng) exec_module() 被實現(xiàn)的時候,導(dǎo)入機(jī)制關(guān)心的是 load_module() 所有其他的責(zé)任。
-
module_repr(module)? 一個遺留方法,在實現(xiàn)時計算并返回給定模塊的 repr,作為字符串。 模塊類型的默認(rèn) repr() 將根據(jù)需要使用此方法的結(jié)果。
3.3 新版功能.
在 3.4 版更改: 是可選的方法而不是一個抽象方法。
3.4 版后已移除: 現(xiàn)在導(dǎo)入機(jī)制會自動地關(guān)注這個方法。
-
-
class
importlib.abc.ResourceReader? 提供讀取 resources 能力的一個 abstract base class 。
從這個 ABC 的視角出發(fā),resource 指一個包附帶的二進(jìn)制文件。常見的如在包的
__init__.py文件旁的數(shù)據(jù)文件。這個類存在的目的是為了將對數(shù)據(jù)文件的訪問進(jìn)行抽象,這樣包就和其數(shù)據(jù)文件的存儲方式無關(guān)了。不論這些文件是存放在一個 zip 文件里還是直接在文件系統(tǒng)內(nèi)。對于該類中的任一方法,resource 參數(shù)的值都需要是一個在概念上表示文件名稱的 path-like object。 這意味著任何子目錄的路徑都不該出現(xiàn)在 resouce 參數(shù)值內(nèi)。 因為對于閱讀器而言,包的位置就代表著「目錄」。 因此目錄和文件名就分別對應(yīng)于包和資源。 這也是該類的實例都需要和一個包直接關(guān)聯(lián)(而不是潛在指代很多包或者一整個模塊)的原因。
想支持資源讀取的加載器需要提供一個返回實現(xiàn)了此 ABC 的接口的
get_resource_reader(fullname)方法。如果通過全名指定的模塊不是一個包,這個方法應(yīng)該返回None。 當(dāng)指定的模塊是一個包時,應(yīng)該只返回一個與這個抽象類ABC兼容的對象。3.7 新版功能.
-
abstractmethod
open_resource(resource)? 返回一個打開的 file-like object 用于 resource 的二進(jìn)制讀取。
如果無法找到資源,將會引發(fā)
FileNotFoundError。
-
abstractmethod
resource_path(resource)? 返回 resource 的文件系統(tǒng)路徑。
如果資源并不實際存在于文件系統(tǒng)中,將會引發(fā)
FileNotFoundError。
-
abstractmethod
is_resource(name)? 如果*name* 被視作資源,則返回True。如果*name*不存在,則引發(fā)
FileNotFoundError異常。
-
abstractmethod
contents()? 反回由字符串組成的 iterable,表示這個包的所有內(nèi)容。 請注意并不要求迭代器返回的所有名稱都是實際的資源,例如返回
is_resource()為假值的名稱也是可接受的。允許非資源名字被返回是為了允許存儲的一個包和它的資源的方式是已知先驗的并且非資源名字會有用的情況。比如,允許返回子目錄名字,目的是當(dāng)?shù)弥唾Y源存儲在文件系統(tǒng)上面的時候,能夠直接使用子目錄的名字。
這個抽象方法返回了一個不包含任何內(nèi)容的可迭代對象。
-
abstractmethod
-
class
importlib.abc.ResourceLoader? 一個 loader 的抽象基類,它實現(xiàn)了可選的 PEP 302 協(xié)議用于從存儲后端加載任意資源。
3.7 版后已移除: 由于要支持使用
importlib.abc.ResourceReader類來加載資源,這個 ABC 已經(jīng)被棄用了。-
abstractmethod
get_data(path)? 一個用于返回位于 path 的字節(jié)數(shù)據(jù)的抽象方法。有一個允許存儲任意數(shù)據(jù)的類文件存儲后端的加載器能夠?qū)崿F(xiàn)這個抽象方法來直接訪問這些被存儲的數(shù)據(jù)。如果不能夠找到 path,則會引發(fā)
OSError異常。path 被希望使用一個模塊的__file屬性或來自一個包的__path__來構(gòu)建。在 3.4 版更改: 引發(fā)
OSError異常而不是NotImplementedError異常。
-
abstractmethod
-
class
importlib.abc.InspectLoader? 一個實現(xiàn)加載器檢查模塊可選的 PEP 302 協(xié)議的 loader 的抽象基類。
-
get_code(fullname)? 返回一個模塊的代碼對象,或如果模塊沒有一個代碼對象(例如,對于內(nèi)置的模塊來說,這會是這種情況),則為
None。 如果加載器不能找到請求的模塊,則引發(fā)ImportError異常。注解
當(dāng)這個方法有一個默認(rèn)的實現(xiàn)的時候,出于性能方面的考慮,如果有可能的話,建議覆蓋它。
在 3.4 版更改: 不再抽象并且提供一個具體的實現(xiàn)。
-
abstractmethod
get_source(fullname)? 一個返回模塊源的抽象方法。使用 universal newlines 作為文本字符串被返回,將所有可識別行分割符翻譯成
'\n'字符。 如果沒有可用的源(例如,一個內(nèi)置模塊),則返回None。 如果加載器不能找到指定的模塊,則引發(fā)ImportError異常。在 3.4 版更改: 引發(fā)
ImportError而不是NotImplementedError。
-
is_package(fullname)? 一個抽象方法,如果這個模塊是一個包則返回真值,否則返回假值。 如果 loader 不能找到這個模塊,則引發(fā)
ImportError。在 3.4 版更改: 引發(fā)
ImportError而不是NotImplementedError。
-
static
source_to_code(data, path='<string>')? 創(chuàng)建一個來自Python源碼的代碼對象。
參數(shù) data 可以是任意
compile()函數(shù)支持的類型(例如字符串或字節(jié)串)。 參數(shù) path 應(yīng)該是源代碼來源的路徑,這可能是一個抽象概念(例如位于一個 zip 文件中)。在有后續(xù)代碼對象的情況下,可以在一個模塊中通過運行``exec(code, module.__dict__)``來執(zhí)行它。
3.4 新版功能.
在 3.5 版更改: 使得這個方法變成靜態(tài)的。
-
exec_module(module)? Loader.exec_module()的實現(xiàn)。3.4 新版功能.
-
load_module(fullname)? Loader.load_module()的實現(xiàn)。3.4 版后已移除: 使用
exec_module()來代替。
-
-
class
importlib.abc.ExecutionLoader? 一個繼承自
InspectLoader的抽象基類,當(dāng)被實現(xiàn)時,幫助一個模塊作為腳本來執(zhí)行。 這個抽象基類表示可選的 PEP 302 協(xié)議。-
abstractmethod
get_filename(fullname)? 一個用來為指定模塊返回
__file__的值的抽象方法。如果無路徑可用,則引發(fā)ImportError。如果源代碼可用,那么這個方法返回源文件的路徑,不管是否是用來加載模塊的字節(jié)碼。
在 3.4 版更改: 引發(fā)
ImportError而不是NotImplementedError。
-
abstractmethod
-
class
importlib.abc.FileLoader(fullname, path)? 一個繼承自
ResourceLoader和ExecutionLoader,提供ResourceLoader.get_data()和ExecutionLoader.get_filename()具體實現(xiàn)的抽象基類。參數(shù)*fullname*是加載器要處理的模塊的完全解析的名字。參數(shù)*path*是模塊文件的路徑。
3.3 新版功能.
-
name? 加載器可以處理的模塊的名字。
-
path? 模塊的文件路徑
-
load_module(fullname)? 調(diào)用super的``load_module()``。
3.4 版后已移除: 使用
Loader.exec_module()來代替。
-
abstractmethod
get_data(path)? 讀取 path 作為二進(jìn)制文件并且返回來自它的字節(jié)數(shù)據(jù)。
-
-
class
importlib.abc.SourceLoader? 一個用于實現(xiàn)源文件(和可選地字節(jié)碼)加載的抽象基類。這個類繼承自
ResourceLoader和ExecutionLoader,需要實現(xiàn):ExecutionLoader.get_filename()應(yīng)該是只返回源文件的路徑;不支持無源加載。
由這個類定義的抽象方法用來添加可選的字節(jié)碼文件支持。不實現(xiàn)這些可選的方法(或?qū)е滤鼈円l(fā)
NotImplementedError異常)導(dǎo)致這個加載器只能與源代碼一起工作。 實現(xiàn)這些方法允許加載器能與源 和 字節(jié)碼文件一起工作。不允許只提供字節(jié)碼的 無源式 加載。字節(jié)碼文件是通過移除 Python 編譯器的解析步驟來加速加載的優(yōu)化,并且因此沒有開放出字節(jié)碼專用的 API。-
path_stats(path)? 返回一個包含關(guān)于指定路徑的元數(shù)據(jù)的
dict的可選的抽象方法。 支持的字典鍵有:'mtime'(必選項): 一個表示源碼修改時間的整數(shù)或浮點數(shù);'size'(可選項):源碼的字節(jié)大小。
字典中任何其他鍵會被忽略,以允許將來的擴(kuò)展。 如果不能處理該路徑,則會引發(fā)
OSError。3.3 新版功能.
在 3.4 版更改: 引發(fā)
OSError而不是NotImplemented。
-
path_mtime(path)? 返回指定文件路徑修改時間的可選的抽象方法。
3.3 版后已移除: 在有了
path_stats()的情況下,這個方法被棄用了。 沒必要去實現(xiàn)它了,但是為了兼容性,它依然處于可用狀態(tài)。 如果文件路徑不能被處理,則引發(fā)OSError異常。在 3.4 版更改: 引發(fā)
OSError而不是NotImplemented。
-
set_data(path, data)? 往一個文件路徑寫入指定字節(jié)的的可選的抽象方法。任何中間不存在的目錄不會被自動創(chuàng)建。
由于路徑是只讀的,當(dāng)寫入的路徑產(chǎn)生錯誤時(
errno.EACCES/PermissionError),不會傳播異常。在 3.4 版更改: 當(dāng)被調(diào)用時,不再引起
NotImplementedError異常。
-
get_code(fullname)? InspectLoader.get_code()的具體實現(xiàn)。
-
exec_module(module)? Loader.exec_module()的具體實現(xiàn)。3.4 新版功能.
-
load_module(fullname)? Concrete implementation of
Loader.load_module().3.4 版后已移除: 使用
exec_module()來代替。
-
get_source(fullname)? InspectLoader.get_source()的具體實現(xiàn)。
-
is_package(fullname)? InspectLoader.is_package()的具體實現(xiàn)。一個模塊被確定為一個包的條件是:它的文件路徑(由ExecutionLoader.get_filename()提供)當(dāng)文件擴(kuò)展名被移除時是一個命名為__init__的文件,并且 這個模塊名字本身不是以``__init__``結(jié)束。
importlib.resources -- 資源?
源碼: Lib/importlib/resources.py
3.7 新版功能.
這個模塊使得Python的導(dǎo)入系統(tǒng)提供了訪問*包*內(nèi)的*資源*的功能。如果能夠?qū)胍粋€包,那么就能夠訪問那個包里面的資源。資源可以以二進(jìn)制或文本模式方式被打開或讀取。
資源非常類似于目錄內(nèi)部的文件,要牢記的是這僅僅是一個比喻。資源和包不是與文件系統(tǒng)上的物理文件和目錄一樣存在著。
注解
本模塊提供了類似于 pkg_resources Basic Resource Access 的功能,但沒有該包的性能開銷。這樣讀取包中的資源就更為容易,語義也更穩(wěn)定一致。
該模塊有獨立的向下移植版本, using importlib.resources 和 migrating from pkg_resources to importlib.resources 提供了更多信息。
加載器想要支持資源讀取應(yīng)該實現(xiàn)一個由 importlib.abc.ResourceReader 指定的``get_resource_reader(fullname)`` 方法。
定義了以下類型。
-
importlib.resources.Package? Package類型定義為Union[str, ModuleType]。這意味著只要函數(shù)說明接受Package的地方,就可以傳入字符串或模塊。模塊對象必須擁有一個可解析的__spec__.submodule_search_locations,不能是None。
-
importlib.resources.Resource? 此類型描述了傳入本包各函數(shù)的資源名稱。定義為
Union[str, os.PathLike]。
有以下函數(shù)可用:
-
importlib.resources.open_binary(package, resource)? 以二進(jìn)制讀方式打開 package 內(nèi)的 resource。
package 是包名或符合
Package要求的模塊對象。 resource 是要在*package* 內(nèi)打開的資源名;不能包含路徑分隔符,也不能有子資源(即不能為目錄)。本函數(shù)將返回一個``typing.BinaryIO`` 實例,即一個供讀取的已打開的二進(jìn)制 I/O 流。
-
importlib.resources.open_text(package, resource, encoding='utf-8', errors='strict')? 以文本讀方式打開 package 內(nèi)的 resource。默認(rèn)情況下,資源將以 UTF-8 格式打開以供讀取。
package 是包名或符合
Package要求的模塊對象。 resource 是要在 package 內(nèi)打開的資源名;不能包含路徑分隔符,也不能有子資源(即不能是目錄)。encoding 和 errors 的含義與內(nèi)置open()的一樣。本函數(shù)返回一個
typing.TextIO實例,即一個打開的文本 I/O 流對象以供讀取。
-
importlib.resources.read_binary(package, resource)? 讀取并返回 package 中的 resource 內(nèi)容,格式為
bytes。package 是包名或符合
Package要求的模塊對象。 resource 是要在 package 內(nèi)打開的資源名;不能包含路徑分隔符,也不能有子資源(即不能是目錄)。資源內(nèi)容以bytes的形式返回。
-
importlib.resources.read_text(package, resource, encoding='utf-8', errors='strict')? 讀取并返回 package 中 resource 的內(nèi)容,格式為
str。默認(rèn)情況下,資源內(nèi)容將以嚴(yán)格的 UTF-8 格式讀取。package 是包名或符合
Package要求的模塊對象。 resource 是要在 package 內(nèi)打開的資源名;不能包含路徑分隔符,也不能有子資源(即不能是目錄)。encoding 和 errors 的含義與內(nèi)置open()的一樣。資源內(nèi)容將以str的形式返回。
-
importlib.resources.path(package, resource)? 返回 resource 實際的文件系統(tǒng)路徑。本函數(shù)返回一個上下文管理器,以供
with語句中使用。上下文管理器提供一個pathlib.Path對象。退出上下文管理程序時,可以清理所有臨時文件,比如從壓縮文件中提取資源時創(chuàng)建的那些文件。
package 是包名或符合
Package要求的模塊對象。 resource 是要在 package 內(nèi)打開的資源名;不能包含路徑分隔符,也不能有子資源(即不能是目錄)。
-
importlib.resources.is_resource(package, name)? 如果包中存在名為 name 的資源,則返回
True,否則返回False。 請記住,目錄 不是 資源! package 為包名或一個符合Package要求的模塊對象。
importlib.machinery —— 導(dǎo)入器和路徑鉤子函數(shù)。?
源代碼: Lib/importlib/machinery.py
本模塊包含多個對象,以幫助 import 查找并加載模塊。
-
importlib.machinery.SOURCE_SUFFIXES? 一個字符串列表,表示源模塊的可識別的文件后綴。
3.3 新版功能.
-
importlib.machinery.DEBUG_BYTECODE_SUFFIXES? 一個字符串列表,表示未經(jīng)優(yōu)化字節(jié)碼模塊的文件后綴。
3.3 新版功能.
3.5 版后已移除: 改用
BYTECODE_SUFFIXES。
-
importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES? 一個字符串列表,表示已優(yōu)化字節(jié)碼模塊的文件后綴。
3.3 新版功能.
3.5 版后已移除: 改用
BYTECODE_SUFFIXES。
-
importlib.machinery.BYTECODE_SUFFIXES? 一個字符串列表,表示字節(jié)碼模塊的可識別的文件后綴(包含前導(dǎo)的句點符號)。
3.3 新版功能.
在 3.5 版更改: 該值不再依賴于
__debug__。
-
importlib.machinery.EXTENSION_SUFFIXES? 一個字符串列表,表示擴(kuò)展模塊的可識別的文件后綴。
3.3 新版功能.
-
importlib.machinery.all_suffixes()? 返回字符串的組合列表,代表標(biāo)準(zhǔn)導(dǎo)入機(jī)制可識別模塊的所有文件后綴。這是個助手函數(shù),只需知道某個文件系統(tǒng)路徑是否會指向模塊,而不需要任何關(guān)于模塊種類的細(xì)節(jié)(例如
inspect.getmodulename())。3.3 新版功能.
-
class
importlib.machinery.BuiltinImporter? 用于導(dǎo)入內(nèi)置模塊的 importer。 所有已知的內(nèi)置模塊都已列入
sys.builtin_module_names。 此類實現(xiàn)了importlib.abc.MetaPathFinder和importlib.abc.InspectLoader抽象基類。此類只定義類的方法,以減輕實例化的開銷。
在 3.5 版更改: 作為 PEP 489 的一部分,現(xiàn)在內(nèi)置模塊導(dǎo)入器實現(xiàn)了
Loader.create_module()和Loader.exec_module()。
-
class
importlib.machinery.FrozenImporter? 用于已凍結(jié)模塊的 importer。 此類實現(xiàn)了
importlib.abc.MetaPathFinder和importlib.abc.InspectLoader抽象基類。此類只定義類的方法,以減輕實例化的開銷。
在 3.4 版更改: 有了
create_module()和exec_module()方法。
-
class
importlib.machinery.WindowsRegistryFinder? Finder for modules declared in the Windows registry. This class implements the
importlib.abc.MetaPathFinderABC.此類只定義類的方法,以減輕實例化的開銷。
3.3 新版功能.
3.6 版后已移除: 改用
site配置。未來版本的 Python 可能不會默認(rèn)啟用該查找器。
-
class
importlib.machinery.PathFinder? A Finder for
sys.pathand package__path__attributes. This class implements theimportlib.abc.MetaPathFinderABC.此類只定義類的方法,以減輕實例化的開銷。
-
classmethod
find_spec(fullname, path=None, target=None)? 類方法試圖在
sys.path或 path 上為 fullname 指定的模塊查找 spec。對于每個路徑條目,都會查看sys.path_importer_cache。如果找到非 False 的對象,則將其用作 path entry finder 來查找要搜索的模塊。如果在sys.path_importer_cache中沒有找到條目,那會在sys.path_hooks檢索該路徑條目的查找器,找到了則和查到的模塊信息一起存入sys.path_importer_cache。如果查找器沒有找到,則緩存中的查找器和模塊信息都存為None,并返回。3.4 新版功能.
在 3.5 版更改: 如果當(dāng)前工作目錄不再有效(用空字符串表示),則返回
None,但在sys.path_importer_cache中不會有緩存值。
-
classmethod
find_module(fullname, path=None)? 一個過時的
find_spec()封裝對象。3.4 版后已移除: 使用
find_spec()來代替。
-
classmethod
invalidate_caches()? 為所有存于
sys.path_importer_cache中的查找器,調(diào)用其importlib.abc.PathEntryFinder.invalidate_caches()方法。sys.path_importer_cache中為None的條目將被刪除。在 3.7 版更改:
sys.path_importer_cache中的None條目將被刪除。
在 3.4 版更改: 調(diào)用
sys.path_hooks中的對象,當(dāng)前工作目錄為''(即空字符串)。-
classmethod
-
class
importlib.machinery.FileFinder(path, *loader_details)? importlib.abc.PathEntryFinder的一個具體實現(xiàn),它會緩存來自文件系統(tǒng)的結(jié)果。參數(shù) path 是查找器負(fù)責(zé)搜索的目錄。
loader_details 參數(shù)是數(shù)量不定的二元組,每個元組包含加載器及其可識別的文件后綴列表。加載器應(yīng)為可調(diào)用對象,可接受兩個參數(shù),即模塊的名稱和已找到文件的路徑。
查找器將按需對目錄內(nèi)容進(jìn)行緩存,通過對每個模塊的檢索進(jìn)行狀態(tài)統(tǒng)計,驗證緩存是否過期。因為緩存的滯后性依賴于操作系統(tǒng)文件系統(tǒng)狀態(tài)信息的粒度,所以搜索模塊、新建文件、然后搜索新文件代表的模塊,這會存在競爭狀態(tài)。如果這些操作的頻率太快,甚至小于狀態(tài)統(tǒng)計的粒度,那么模塊搜索將會失敗。為了防止這種情況發(fā)生,在動態(tài)創(chuàng)建模塊時,請確保調(diào)用
importlib.invalidate_caches()。3.3 新版功能.
-
path? 查找器將要搜索的路徑。
-
invalidate_caches()? 清理內(nèi)部緩存。
-
classmethod
path_hook(*loader_details)? 一個類方法,返回供
sys.path_hooks使用的閉包。根據(jù)直接給出的路徑參數(shù)和間接給出的 loader_details,閉包會返回一個FileFinder的實例。如果給閉包的參數(shù)不是已存在的目錄,將會觸發(fā)
ImportError。
-
-
class
importlib.machinery.SourceFileLoader(fullname, path)? importlib.abc.SourceLoader的一個具體實現(xiàn),該實現(xiàn)子類化了importlib.abc.FileLoader并提供了其他一些方法的具體實現(xiàn)。3.3 新版功能.
-
name? 該加載器將要處理的模塊名稱。
-
path? 源文件的路徑
-
path_stats(path)? importlib.abc.SourceLoader.path_stats()的具體代碼實現(xiàn)。
-
set_data(path, data)? importlib.abc.SourceLoader.set_data()的具體代碼實現(xiàn)。
-
load_module(name=None)? importlib.abc.Loader.load_module()的具體代碼實現(xiàn),這里要加載的模塊名是可選的。3.6 版后已移除: 改用
importlib.abc.Loader.exec_module()。
-
-
class
importlib.machinery.SourcelessFileLoader(fullname, path)? importlib.abc.FileLoader的具體代碼實現(xiàn),可導(dǎo)入字節(jié)碼文件(也即源代碼文件不存在)。請注意,直接用字節(jié)碼文件(而不是源代碼文件),會讓模塊無法應(yīng)用于所有的 Python 版本或字節(jié)碼格式有所改動的新版本 Python。
3.3 新版功能.
-
name? 加載器將要處理的模塊名。
-
path? 二進(jìn)制碼文件的路徑。
-
get_source(fullname)? 因為用此加載器時字節(jié)碼文件沒有源碼文件,所以返回
None。
-
load_module(name=None)?
importlib.abc.Loader.load_module()的具體代碼實現(xiàn),這里要加載的模塊名是可選的。3.6 版后已移除: 改用
importlib.abc.Loader.exec_module()。-
-
class
importlib.machinery.ExtensionFileLoader(fullname, path)? importlib.abc.ExecutionLoader的具體代碼實現(xiàn),用于擴(kuò)展模塊。參數(shù) fullname 指定了加載器要支持的模塊名。參數(shù) path 是指向擴(kuò)展模塊文件的路徑。
3.3 新版功能.
-
name? 裝載器支持的模塊名。
-
path? 擴(kuò)展模塊的路徑。
-
is_package(fullname)? 根據(jù)
EXTENSION_SUFFIXES,如果文件路徑指向某個包的__init__模塊,則返回True。
-
get_code(fullname)? 返回
None,因為擴(kuò)展模塊缺少代碼對象。
-
get_source(fullname)? 返回
None,因為擴(kuò)展模塊沒有源代碼。
-
-
class
importlib.machinery.ModuleSpec(name, loader, *, origin=None, loader_state=None, is_package=None)? 關(guān)于模塊導(dǎo)入系統(tǒng)相關(guān)狀態(tài)的規(guī)范。通常這是作為模塊的
__spec__屬性暴露出來。 在以下描述中,括號里的名字給出了模塊對象中直接可用的屬性。比如module.__spec__.origin == module.__file__。 但是請注意,雖然 值 通常是相等的,但它們可以不同,因為兩個對象之間沒有進(jìn)行同步。因此__path__有可能在運行時做過更新,而這不會自動反映在__spec__.submodule_search_locations中。3.4 新版功能.
-
name?
(
__name__)一個字符串,表示模塊的完全限定名稱。
-
loader?
(
__loader__)The loader to use for loading. For namespace packages this should be set to
None.-
origin?
(
__file__)裝載模塊所在位置的名稱,如內(nèi)置模塊為 “buildin”,從源代碼加載的模塊為文件名。通常應(yīng)設(shè)置 “origin” ,但它可能為
None(默認(rèn)值),表示未指定 (如命名空間包)。-
submodule_search_locations?
(
__path__)如果是包(否則為 ),子模塊所在位置的字符串列表(否則為
None)。-
loader_state?
依模塊不同的額外數(shù)據(jù)的容器,以供加載過程中使用(或
None)。-
cached?
(
__cached__)字符串,表示編譯后的模塊所在位置(或
None)。-
parent?
(
__package__)(Read-only) Fully-qualified name of the package to which the module belongs as a submodule (or
None).-
has_location?
布爾值,表示模塊的“origin”屬性是否指向可加載的位置。
-
importlib.util —— 導(dǎo)入器的工具程序代碼?
本模塊包含了幫助構(gòu)建 importer 的多個對象。
-
importlib.util.MAGIC_NUMBER? 代表字節(jié)碼版本號的字節(jié)串。若要有助于加載/寫入字節(jié)碼,可考慮采用
importlib.abc.SourceLoader。3.4 新版功能.
-
importlib.util.cache_from_source(path, debug_override=None, *, optimization=None)? 返回 PEP 3147/PEP 488 定義的,與源 path 相關(guān)聯(lián)的已編譯字節(jié)碼文件的路徑。 例如,如果 path 為
/foo/bar/baz.py則 Python 3.2 中的返回值將是/foo/bar/__pycache__/baz.cpython-32.pyc。 字符串cpython-32來自于當(dāng)前的魔法標(biāo)簽 (參見get_tag(); 如果sys.implementation.cache_tag未定義則將會引發(fā)NotImplementedError)。The optimization parameter is used to specify the optimization level of the bytecode file. An empty string represents no optimization, so
/foo/bar/baz.pywith an optimization of''will result in a bytecode path of/foo/bar/__pycache__/baz.cpython-32.pyc.Nonecauses the interpter's optimization level to be used. Any other value's string representation being used, so/foo/bar/baz.pywith an optimization of2will lead to the bytecode path of/foo/bar/__pycache__/baz.cpython-32.opt-2.pyc. The string representation of optimization can only be alphanumeric, elseValueErroris raised.debug_override 參數(shù)已廢棄,可用于覆蓋系統(tǒng)的
__debug__值。True值相當(dāng)于將 optimization 設(shè)為空字符串。False則相當(dāng)于*optimization* 設(shè)為1。如果 debug_override 和 optimization 都不為None,則會觸發(fā)TypeError。3.4 新版功能.
在 3.5 版更改: 增加了 optimization 參數(shù),廢棄了 debug_override 參數(shù)。
在 3.6 版更改: 接受一個 path-like object。
-
importlib.util.source_from_cache(path)? 根據(jù)指向一個 PEP 3147 文件名的 path,返回相關(guān)聯(lián)的源代碼文件路徑。 舉例來說,如果 path 為
/foo/bar/__pycache__/baz.cpython-32.pyc則返回的路徑將是/foo/bar/baz.py。 path 不需要已存在,但如果它未遵循 PEP 3147 或 PEP 488 的格式,則會引發(fā)ValueError。 如果未定義sys.implementation.cache_tag,則會引發(fā)NotImplementedError。3.4 新版功能.
在 3.6 版更改: 接受一個 path-like object。
-
importlib.util.decode_source(source_bytes)? 對代表源代碼的字節(jié)串進(jìn)行解碼,并將其作為帶有通用換行符的字符串返回(符合
importlib.abc.InspectLoader.get_source()要求)。3.4 新版功能.
-
importlib.util.resolve_name(name, package)? 將模塊的相對名稱解析為絕對名稱。
If name has no leading dots, then name is simply returned. This allows for usage such as
importlib.util.resolve_name('sys', __package__)without doing a check to see if the package argument is needed.ValueErroris raised if name is a relative module name but package is a false value (e.g.Noneor the empty string).ValueErroris also raised a relative name would escape its containing package (e.g. requesting..baconfrom within thespampackage).3.3 新版功能.
-
importlib.util.find_spec(name, package=None)? 查找模塊的 spec,可選相對指定的 包 名。如果該模塊位于
sys.modules中,則會返回sys.modules[name].__spec__(除非 spec為None或未作設(shè)置,這時會觸發(fā)ValueError)。否則將用sys.meta_path進(jìn)行搜索。若找不到則返回None。如果 name 為一個子模塊(帶有一個句點),則會自動導(dǎo)入父級模塊。
name 和 package 的用法與
import_module()相同。3.4 新版功能.
在 3.7 版更改: 如果 package 實際上不是一個包(即缺少
__path__屬性)則會引發(fā)ModuleNotFoundError而不是AttributeError。
-
importlib.util.module_from_spec(spec)? 基于 spec 和
spec.loader.create_module創(chuàng)建一個新模塊。如果
spec.loader.create_module未返回None,那么先前已存在的屬性不會被重置。另外,如果AttributeError是在訪問 spec 或設(shè)置模塊屬性時觸發(fā)的,則不會觸發(fā) 。本函數(shù)比
types.ModuleType創(chuàng)建新模塊要好,因為用到 spec 模塊設(shè)置了盡可能多的導(dǎo)入控制屬性。3.5 新版功能.
-
@importlib.util.module_for_loader? importlib.abc.Loader.load_module()的一個 decorator,用來選取合適的模塊對象以供加載。被裝飾方法的簽名應(yīng)帶有兩個位置參數(shù)(如:load_module(self, module)),其中第二個參數(shù)將是加載器用到的模塊 對象。請注意,由于假定有兩個參數(shù),所以裝飾器對靜態(tài)方法不起作用。裝飾的方法將接受要加載的模塊的 name,正如 loader 一樣。如果在
sys.modules中沒有找到該模塊,那么將構(gòu)造一個新模塊。不管模塊來自哪里,__loader__設(shè)置為 self ,并且__package__是根據(jù)importlib.abc.InspectLoader.is_package()的返回值設(shè)置的。這些屬性會無條件進(jìn)行設(shè)置以便支持重載。如果被裝飾的方法觸發(fā)異常,并且已有模塊加入
sys.modules中,那么該模塊將被移除,以防sys.modules中殘留一個部分初始化的模塊。如果該模塊原先已在sys.modules中,則會保留。在 3.3 版更改: 有可能時自動設(shè)置
__loader__和__package__。在 3.4 版更改: 無條件設(shè)置
__name__、__loader__、__package__以支持再次加載。3.4 版后已移除: 現(xiàn)在,導(dǎo)入機(jī)制直接執(zhí)行本函數(shù)提供的所有功能。
-
@importlib.util.set_loader? 一個 decorator,用于
importlib.abc.Loader.load_module()在返回的模塊上設(shè)置__loader__屬性。如果該屬性已被設(shè)置,裝飾器就什么都不做。這里假定被封裝方法的第一個位置參數(shù)(即self)就是__loader__要設(shè)置的。在 3.4 版更改: 如果設(shè)為
None,則會去設(shè)置__loader__,就像該屬性不存在一樣。3.4 版后已移除: 現(xiàn)在導(dǎo)入機(jī)制會自動用到本方法。
-
@importlib.util.set_package? 一個用于
importlib.abc.Loader.load_module()的 decorator ,以便設(shè)置返回模塊的__package__屬性。如果__package__已設(shè)置且不為None,則不會做改動。3.4 版后已移除: 現(xiàn)在導(dǎo)入機(jī)制會自動用到本方法。
-
importlib.util.spec_from_loader(name, loader, *, origin=None, is_package=None)? 一個工廠函數(shù),用于創(chuàng)建基于加載器的
ModuleSpec實例。 形參的含義與 ModuleSpec 的相同。 該函數(shù)會利用當(dāng)前可用的 loader API,比如InspectLoader.is_package(),以填充所有缺失的規(guī)格信息。3.4 新版功能.
-
importlib.util.spec_from_file_location(name, location, *, loader=None, submodule_search_locations=None)? 一個工廠函數(shù),用于創(chuàng)建基于文件路徑的
ModuleSpec實例。 缺失的信息將通過利用加載器 API 以及模塊將基于文件的隱含條件在 spec 上進(jìn)行填充。3.4 新版功能.
在 3.6 版更改: 接受一個 path-like object。
-
importlib.util.source_hash(source_bytes)? 以字節(jié)串的形式返回 source_bytes 的哈希值。基于哈希值的
.pyc文件在頭部嵌入了對應(yīng)源文件內(nèi)容的source_hash()。3.7 新版功能.
-
class
importlib.util.LazyLoader(loader)? 此類會延遲執(zhí)行模塊加載器,直至該模塊有一個屬性被訪問到。
此類 只 適用于定義了
exec_module()的加載器,因為需要控制模塊的類型。 同理,加載器的create_module()方法必須返回None或__class__屬性可被改變且不用 slots 的類型。 最后,用于替換sys.modules內(nèi)容的模塊將無法工作,因為無法在整個解釋器中安全地替換模塊的引用;如果檢測到這種替換,將觸發(fā)ValueError。注解
如果項目對啟動時間要求很高,只要模塊未被用過,此類能夠最小化加載模塊的開銷。對于啟動時間并不重要的項目來說,由于加載過程中產(chǎn)生的錯誤信息會被暫時擱置,因此強(qiáng)烈不建議使用此類。
3.5 新版功能.
在 3.6 版更改: 開始調(diào)用
create_module(),移除importlib.machinery.BuiltinImporter和importlib.machinery.ExtensionFileLoader的兼容性警告。-
classmethod
factory(loader)? 靜態(tài)方法,返回創(chuàng)建延遲加載器的可調(diào)用對象。就是說用在加載器用類而不是實例傳遞的場合。
suffixes = importlib.machinery.SOURCE_SUFFIXES loader = importlib.machinery.SourceFileLoader lazy_loader = importlib.util.LazyLoader.factory(loader) finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))
-
classmethod
例子?
用編程方式導(dǎo)入?
要以編程方式導(dǎo)入一個模塊,請使用 importlib.import_module() :
import importlib
itertools = importlib.import_module('itertools')
檢查某模塊可否導(dǎo)入。?
若要查看某個模塊是否可導(dǎo)入,但不需要實際執(zhí)行導(dǎo)入,則應(yīng)使用 importlib.util.find_spec() :
import importlib.util
import sys
# For illustrative purposes.
name = 'itertools'
spec = importlib.util.find_spec(name)
if spec is None:
print("can't find the itertools module")
else:
# If you chose to perform the actual import ...
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Adding the module to sys.modules is optional.
sys.modules[name] = module
直接導(dǎo)入源文件。?
若要直接導(dǎo)入 Python 源碼文件,請使用一下方案(僅 Python 3.5 以上版本有效):
import importlib.util
import sys
# For illustrative purposes.
import tokenize
file_path = tokenize.__file__
module_name = tokenize.__name__
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Optional; only necessary if you want to be able to import the module
# by name later.
sys.modules[module_name] = module
設(shè)置導(dǎo)入器?
對于深度定制的導(dǎo)入,通常需要實現(xiàn)一個 importer。 這意味著得同時管理 finder 和 loader。 根據(jù)不同的需求,有兩種類型的查找器可供選擇: meta path finder 或 path entry finder。 前者應(yīng)位于 sys.meta_path 之上,而后者是用 path entry hook 在 sys.path_hooks 上創(chuàng)建但與 sys.path 一起工作,可能會創(chuàng)建一個查找器。以下例子將演示如何注冊自己的導(dǎo)入器,以供導(dǎo)入使用(關(guān)于自建導(dǎo)入器請閱讀本包內(nèi)定義的類文檔):
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() 的近似實現(xiàn)?
導(dǎo)入過程本身是用 Python 代碼實現(xiàn)的,這樣就能通過 importlib 將大多數(shù)導(dǎo)入機(jī)制暴露出來。以下代碼近似實現(xiàn)了 importlib.import_module() ,以幫助說明 importlib 暴露出來的各種 API (importlib 的用法適用于 Python 3.4 以上版本 ,其他代碼適用于 Python 3.6 以上版本)。
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)
spec.loader.exec_module(module)
sys.modules[absolute_name] = module
if path is not None:
setattr(parent_module, child_name, module)
return module
