importlib
--- import
的實(shí)現(xiàn)?
3.1 新版功能.
概述?
The purpose of the importlib
package is three-fold.
One is to provide the
implementation of the import
statement (and thus, by extension, the
__import__()
function) in Python source code. This provides an
implementation of import
which is portable to any Python
interpreter. This also provides an implementation which is easier to
comprehend than one implemented in a programming language other than Python.
第二個(gè)目的是實(shí)現(xiàn) import
的部分被公開在這個(gè)包中,使得用戶更容易創(chuàng)建他們自己的自定義對(duì)象 (通常被稱為 importer) 來(lái)參與到導(dǎo)入過(guò)程中。
Three, the package contains modules exposing additional functionality for managing aspects of Python packages:
importlib.metadata
presents access to metadata from third-party distributions.importlib.resources
provides routines for accessing non-code "resources" from Python packages.
參見(jiàn)
- import 語(yǔ)句
import
語(yǔ)句的語(yǔ)言參考- 包規(guī)格說(shuō)明
包的初始規(guī)范。自從編寫這個(gè)文檔開始,一些語(yǔ)義已經(jīng)發(fā)生改變了(比如基于
sys.modules
中None
的重定向)。__import__()
函數(shù)import
語(yǔ)句是這個(gè)函數(shù)的語(yǔ)法糖。- The initialization of the sys.path module search path
The initialization of
sys.path
.- PEP 235
在忽略大小寫的平臺(tái)上進(jìn)行導(dǎo)入
- PEP 263
定義 Python 源代碼編碼
- PEP 302
新導(dǎo)入鉤子
- PEP 328
導(dǎo)入:多行和絕對(duì)/相對(duì)
- PEP 366
主模塊顯式相對(duì)導(dǎo)入
- PEP 420
隱式命名空間包
- PEP 451
導(dǎo)入系統(tǒng)的一個(gè)模塊規(guī)范類型
- PEP 488
消除PYO文件
- PEP 489
多階段擴(kuò)展模塊初始化
- PEP 552
確定性的 pyc 文件
- PEP 3120
使用 UTF-8 作為默認(rèn)的源編碼
- PEP 3147
PYC 倉(cāng)庫(kù)目錄
函數(shù)?
- importlib.__import__(name, globals=None, locals=None, fromlist=(), level=0)?
內(nèi)置
__import__()
函數(shù)的實(shí)現(xiàn)。備注
程序式地導(dǎo)入模塊應(yīng)該使用
import_module()
而不是這個(gè)函數(shù)。
- importlib.import_module(name, package=None)?
導(dǎo)入一個(gè)模塊。參數(shù) name 指定了以絕對(duì)或相對(duì)導(dǎo)入方式導(dǎo)入什么模塊 (比如要么像這樣
pkg.mod
或者這樣..mod
)。如果參數(shù) name 使用相對(duì)導(dǎo)入的方式來(lái)指定,那么那個(gè)參數(shù) packages 必須設(shè)置為那個(gè)包名,這個(gè)包名作為解析這個(gè)包名的錨點(diǎn) (比如import_module('..mod', 'pkg.subpkg')
將會(huì)導(dǎo)入pkg.mod
)。import_module()
函數(shù)是一個(gè)對(duì)importlib.__import__()
進(jìn)行簡(jiǎn)化的包裝器。 這意味著該函數(shù)的所有主義都來(lái)自于importlib.__import__()
。 這兩個(gè)函數(shù)之間最重要的不同點(diǎn)在于import_module()
返回指定的包或模塊 (例如pkg.mod
),而__import__()
返回最高層級(jí)的包或模塊 (例如pkg
)。如果動(dòng)態(tài)導(dǎo)入一個(gè)自從解釋器開始執(zhí)行以來(lái)被創(chuàng)建的模塊(即創(chuàng)建了一個(gè) Python 源代碼文件),為了讓導(dǎo)入系統(tǒng)知道這個(gè)新模塊,可能需要調(diào)用
invalidate_caches()
。在 3.3 版更改: 父包會(huì)被自動(dòng)導(dǎo)入。
- importlib.find_loader(name, path=None)?
查找一個(gè)模塊的加載器,可選擇地在指定的 path 里面。如果這個(gè)模塊是在
sys.modules
,那么返回sys.modules[name].__loader__
(除非這個(gè)加載器是None
或者是沒(méi)有被設(shè)置, 在這樣的情況下,會(huì)引起ValueError
異常)。 否則使用sys.meta_path
的一次搜索就結(jié)束。如果未發(fā)現(xiàn)加載器,則返回None
。點(diǎn)狀的名稱沒(méi)有使得它父包或模塊隱式地導(dǎo)入,因?yàn)樗枰虞d它們并且可能不需要。為了適當(dāng)?shù)貙?dǎo)入一個(gè)子模塊,需要導(dǎo)入子模塊的所有父包并且使用正確的參數(shù)提供給 path。
3.3 新版功能.
在 3.4 版更改: 如果沒(méi)有設(shè)置
__loader__
,會(huì)引起ValueError
異常,就像屬性設(shè)置為None
的時(shí)候一樣。3.4 版后已移除: 使用
importlib.util.find_spec()
來(lái)代替。
- importlib.invalidate_caches()?
使查找器存儲(chǔ)在
sys.meta_path
中的內(nèi)部緩存無(wú)效。如果一個(gè)查找器實(shí)現(xiàn)了invalidate_caches()
,那么它會(huì)被調(diào)用來(lái)執(zhí)行那個(gè)無(wú)效過(guò)程。 如果創(chuàng)建/安裝任何模塊,同時(shí)正在運(yùn)行的程序是為了保證所有的查找器知道新模塊的存在,那么應(yīng)該調(diào)用這個(gè)函數(shù)。3.3 新版功能.
在 3.10 版更改: Namespace packages created/installed in a different
sys.path
location after the same namespace was already imported are noticed.
- importlib.reload(module)?
重新加載之前導(dǎo)入的 module。 那個(gè)參數(shù)必須是一個(gè)模塊對(duì)象,所以它之前必須已經(jīng)成功導(dǎo)入了。 這在你已經(jīng)使用外部編輯器編輯過(guò)了那個(gè)模塊的源代碼文件并且想在退出 Python 解釋器之前試驗(yàn)這個(gè)新版本的模塊的時(shí)候?qū)⒑苓m用。 函數(shù)的返回值是那個(gè)模塊對(duì)象(如果重新導(dǎo)入導(dǎo)致一個(gè)不同的對(duì)象放置在
sys.modules
中,那么那個(gè)模塊對(duì)象是有可能會(huì)不同)。當(dāng)執(zhí)行
reload()
的時(shí)候:Python 模塊的代碼會(huì)被重新編譯并且那個(gè)模塊級(jí)的代碼被重新執(zhí)行,通過(guò)重新使用一開始加載那個(gè)模塊的 loader,定義一個(gè)新的綁定在那個(gè)模塊字典中的名稱的對(duì)象集合。擴(kuò)展模塊的``init``函數(shù)不會(huì)被調(diào)用第二次。
與Python中的所有的其它對(duì)象一樣,舊的對(duì)象只有在它們的引用計(jì)數(shù)為0之后才會(huì)被回收。
模塊命名空間中的名稱重新指向任何新的或更改后的對(duì)象。
其他舊對(duì)象的引用(例如那個(gè)模塊的外部名稱)不會(huì)被重新綁定到引用的新對(duì)象的,并且如果有需要,必須在出現(xiàn)的每個(gè)命名空間中進(jìn)行更新。
有一些其他注意事項(xiàng):
當(dāng)一個(gè)模塊被重新加載的時(shí)候,它的字典(包含了那個(gè)模塊的全區(qū)變量)會(huì)被保留。名稱的重新定義會(huì)覆蓋舊的定義,所以通常來(lái)說(shuō)這不是問(wèn)題。如果一個(gè)新模塊沒(méi)有定義在舊版本模塊中定義的名稱,則將保留舊版本中的定義。這一特性可用于作為那個(gè)模塊的優(yōu)點(diǎn),如果它維護(hù)一個(gè)全局表或者對(duì)象的緩存 —— 使用
try
語(yǔ)句,就可以測(cè)試表的存在并且跳過(guò)它的初始化,如果有需要的話:try: cache except NameError: cache = {}
重新加載內(nèi)置的或者動(dòng)態(tài)加載模塊,通常來(lái)說(shuō)不是很有用處。不推薦重新加載"
sys
,__main__
,builtins
和其它關(guān)鍵模塊。在很多例子中,擴(kuò)展模塊并不是設(shè)計(jì)為不止一次的初始化,并且當(dāng)重新加載時(shí),可能會(huì)以任意方式失敗。如果一個(gè)模塊使用
from
...import
... 導(dǎo)入的對(duì)象來(lái)自另外一個(gè)模塊,給其它模塊調(diào)用reload()
不會(huì)重新定義來(lái)自這個(gè)模塊的對(duì)象 —— 解決這個(gè)問(wèn)題的一種方式是重新執(zhí)行from
語(yǔ)句,另一種方式是使用import
和限定名稱(module.name)來(lái)代替。如果一個(gè)模塊創(chuàng)建一個(gè)類的實(shí)例,重新加載定義那個(gè)類的模塊不影響那些實(shí)例的方法定義———它們繼續(xù)使用舊類中的定義。對(duì)于子類來(lái)說(shuō)同樣是正確的。
3.4 新版功能.
在 3.7 版更改: 如果重新加載的模塊缺少
ModuleSpec
,則會(huì)觸發(fā)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 的一個(gè)抽象基類
3.3 版后已移除: 使用
MetaPathFinder
或PathEntryFinder
來(lái)代替。- abstractmethod find_module(fullname, path=None)?
為指定的模塊查找 loader 定義的抽象方法。本來(lái)是在 PEP 302 指定的,這個(gè)方法是在
sys.meta_path
和基于路徑的導(dǎo)入子系統(tǒng)中使用。在 3.4 版更改: 當(dāng)被調(diào)用的時(shí)候,返回
None
而不是引發(fā)NotImplementedError
。3.10 版后已移除: 改為實(shí)現(xiàn)
MetaPathFinder.find_spec()
或PathEntryFinder.find_spec()
。
- class importlib.abc.MetaPathFinder?
An abstract base class representing a meta path finder.
3.3 新版功能.
在 3.10 版更改: 不再是
Finder
的子類。- find_spec(fullname, path, target=None)?
一個(gè)抽象方法,用于查找指定模塊的 spec 。若是頂層導(dǎo)入,path 將為
None
。 否則就是查找子包或模塊,path 將是父級(jí)包的__path__
值。找不到則會(huì)返回None
。傳入的target
是一個(gè)模塊對(duì)象,查找器可以用來(lái)對(duì)返回的規(guī)格進(jìn)行更有依據(jù)的猜測(cè)。在實(shí)現(xiàn)具體的MetaPathFinders
代碼時(shí),可能會(huì)用到importlib.util.spec_from_loader()
。3.4 新版功能.
- find_module(fullname, path)?
一個(gè)用于查找指定的模塊中 loader 的遺留方法。如果這是最高層級(jí)的導(dǎo)入,path 的值將會(huì)是
None
。否則,這是一個(gè)查找子包或者模塊的方法,并且 path 的值將會(huì)是來(lái)自父包的__path__
的值。如果未發(fā)現(xiàn)加載器,返回None
。如果定義了
find_spec()
方法,則提供了向后兼容的功能。在 3.4 版更改: 當(dāng)調(diào)用這個(gè)方法的時(shí)候返回
None
而不是引發(fā)NotImplementedError
。 可以使用find_spec()
來(lái)提供功能。3.4 版后已移除: 使用
find_spec()
來(lái)代替。
- invalidate_caches()?
當(dāng)被調(diào)用的時(shí)候,一個(gè)可選的方法應(yīng)該將查找器使用的任何內(nèi)部緩存進(jìn)行無(wú)效。將在
sys.meta_path
上的所有查找器的緩存進(jìn)行無(wú)效的時(shí)候,這個(gè)函數(shù)被importlib.invalidate_caches()
所使用。在 3.4 版更改: 當(dāng)方法被調(diào)用的時(shí)候,方法返回是
None
而不是NotImplemented
。
- class importlib.abc.PathEntryFinder?
一個(gè)抽象基類,代表 path entry finder。雖然與
MetaPathFinder
有些相似之處,但 PathEntryFinder 僅用于importlib.machinery.PathFinder
提供的基于路徑的導(dǎo)入子系統(tǒng)中。3.3 新版功能.
在 3.10 版更改: 不再是
Finder
的子類。- find_spec(fullname, target=None)?
一個(gè)抽象方法,用于查找指定模塊的 spec。搜索器將只在指定的 path entry 內(nèi)搜索該模塊。找不到則會(huì)返回
None
。在實(shí)現(xiàn)具體的PathEntryFinders
代碼時(shí),可能會(huì)用到importlib.util.spec_from_loader()
。3.4 新版功能.
- find_loader(fullname)?
一個(gè)用于在模塊中查找一個(gè) loader 的遺留方法。 返回一個(gè)
(loader, portion)
的2元組,portion
是一個(gè)貢獻(xiàn)給命名空間包部分的文件系統(tǒng)位置的序列。 加載器可能是None
,同時(shí)正在指定的portion
表示的是貢獻(xiàn)給命名空間包的文件系統(tǒng)位置。portion
可以使用一個(gè)空列表來(lái)表示加載器不是命名空間包的一部分。 如果loader
是None
并且portion
是一個(gè)空列表,那么命名空間包中無(wú)加載器或者文件系統(tǒng)位置可查找到(即在那個(gè)模塊中未能找到任何東西)。如果定義了
find_spec()
,則提供了向后兼容的功能。在 3.4 版更改: 返回
(None, [])
而不是引發(fā)NotImplementedError
。 當(dāng)可于提供相應(yīng)的功能的時(shí)候,使用find_spec()
。3.4 版后已移除: 使用
find_spec()
來(lái)代替。
- find_module(fullname)?
Finder.find_module`的具體實(shí)現(xiàn),該方法等價(jià)于``self.find_loader(fullname)[0]`()
。3.4 版后已移除: 使用
find_spec()
來(lái)代替。
- invalidate_caches()?
可選方法,調(diào)用后應(yīng)讓查找器用到的所有內(nèi)部緩存失效。要讓所有緩存的查找器的緩存無(wú)效時(shí),可供
importlib.machinery.PathFinder.invalidate_caches()
調(diào)用。
- class importlib.abc.Loader?
loader 的抽象基類。 關(guān)于一個(gè)加載器的實(shí)際定義請(qǐng)查看 PEP 302。
Loaders that wish to support resource reading should implement a
get_resource_reader()
method as specified byimportlib.abc.ResourceReader
.在 3.7 版更改: Introduced the optional
get_resource_reader()
method.- create_module(spec)?
當(dāng)導(dǎo)入一個(gè)模塊的時(shí)候,一個(gè)返回將要使用的那個(gè)模塊對(duì)象的方法。這個(gè)方法可能返回
None
,這暗示著應(yīng)該發(fā)生默認(rèn)的模塊創(chuàng)建語(yǔ)義。"3.4 新版功能.
在 3.6 版更改: This method is no longer optional when
exec_module()
is defined.
- exec_module(module)?
An abstract method that executes the module in its own namespace when a module is imported or reloaded. The module should already be initialized when
exec_module()
is called. When this method exists,create_module()
must be defined.3.4 新版功能.
在 3.6 版更改:
create_module()
must also be defined.
- load_module(fullname)?
A legacy method for loading a module. If the module cannot be loaded,
ImportError
is raised, otherwise the loaded module is returned.If the requested module already exists in
sys.modules
, that module should be used and reloaded. Otherwise the loader should create a new module and insert it intosys.modules
before any loading begins, to prevent recursion from the import. If the loader inserted a module and the load fails, it must be removed by the loader fromsys.modules
; modules already insys.modules
before the loader began execution should be left alone (seeimportlib.util.module_for_loader()
).The loader should set several attributes on the module (note that some of these attributes can change when a module is reloaded):
__name__
The module's fully-qualified name. It is
'__main__'
for an executed module.
__cached__
The filename of a compiled version of the module's code. It is not set on all modules (e.g. built-in modules).
__path__
The list of locations where the package's submodules will be found. Most of the time this is a single directory. The import system passes this attribute to
__import__()
and to finders in the same way assys.path
but just for the package. It is not set on non-package modules so it can be used as an indicator that the module is a package.
__package__
The fully-qualified name of the package the module is in (or the empty string for a top-level module). If the module is a package then this is the same as
__name__
.
__loader__
The loader used to load the module.
當(dāng)
exec_module()
可用的時(shí)候,那么則提供了向后兼容的功能。在 3.4 版更改: Raise
ImportError
when called instead ofNotImplementedError
. Functionality provided whenexec_module()
is available.3.4 版后已移除: The recommended API for loading a module is
exec_module()
(andcreate_module()
). Loaders should implement it instead ofload_module()
. The import machinery takes care of all the other responsibilities ofload_module()
whenexec_module()
is implemented.
- module_repr(module)?
A legacy method which when implemented calculates and returns the given module's representation, as a string. The module type's default
__repr__()
will use the result of this method as appropriate.3.3 新版功能.
在 3.4 版更改: 是可選的方法而不是一個(gè)抽象方法。
3.4 版后已移除: 現(xiàn)在導(dǎo)入機(jī)制會(huì)自動(dòng)地關(guān)注這個(gè)方法。
- class importlib.abc.ResourceReader?
被 TraversableResources 取代
提供讀取 resources 能力的一個(gè) abstract base class 。
從這個(gè) ABC 的視角出發(fā),resource 指一個(gè)包附帶的二進(jìn)制文件。常見(jiàn)的如在包的
__init__.py
文件旁的數(shù)據(jù)文件。這個(gè)類存在的目的是為了將對(duì)數(shù)據(jù)文件的訪問(wèn)進(jìn)行抽象,這樣包就和其數(shù)據(jù)文件的存儲(chǔ)方式無(wú)關(guān)了。不論這些文件是存放在一個(gè) zip 文件里還是直接在文件系統(tǒng)內(nèi)。對(duì)于該類中的任一方法,resource 參數(shù)的值都需要是一個(gè)在概念上表示文件名稱的 path-like object。 這意味著任何子目錄的路徑都不該出現(xiàn)在 resouce 參數(shù)值內(nèi)。 因?yàn)閷?duì)于閱讀器而言,包的位置就代表著「目錄」。 因此目錄和文件名就分別對(duì)應(yīng)于包和資源。 這也是該類的實(shí)例都需要和一個(gè)包直接關(guān)聯(lián)(而不是潛在指代很多包或者一整個(gè)模塊)的原因。
想支持資源讀取的加載器需要提供一個(gè)返回實(shí)現(xiàn)了此 ABC 的接口的
get_resource_reader(fullname)
方法。如果通過(guò)全名指定的模塊不是一個(gè)包,這個(gè)方法應(yīng)該返回None
。 當(dāng)指定的模塊是一個(gè)包時(shí),應(yīng)該只返回一個(gè)與這個(gè)抽象類ABC兼容的對(duì)象。3.7 新版功能.
- abstractmethod open_resource(resource)?
返回一個(gè)打開的 file-like object 用于 resource 的二進(jìn)制讀取。
如果無(wú)法找到資源,將會(huì)引發(fā)
FileNotFoundError
。
- abstractmethod resource_path(resource)?
返回 resource 的文件系統(tǒng)路徑。
如果資源并不實(shí)際存在于文件系統(tǒng)中,將會(huì)引發(fā)
FileNotFoundError
。
- abstractmethod is_resource(name)?
如果 name 被視作資源,則返回True。如果 name 不存在,則引發(fā)
FileNotFoundError
異常。
- abstractmethod contents()?
反回由字符串組成的 iterable,表示這個(gè)包的所有內(nèi)容。 請(qǐng)注意并不要求迭代器返回的所有名稱都是實(shí)際的資源,例如返回
is_resource()
為假值的名稱也是可接受的。允許非資源名字被返回是為了允許存儲(chǔ)的一個(gè)包和它的資源的方式是已知先驗(yàn)的并且非資源名字會(huì)有用的情況。比如,允許返回子目錄名字,目的是當(dāng)?shù)弥唾Y源存儲(chǔ)在文件系統(tǒng)上面的時(shí)候,能夠直接使用子目錄的名字。
這個(gè)抽象方法返回了一個(gè)不包含任何內(nèi)容的可迭代對(duì)象。
- class importlib.abc.ResourceLoader?
一個(gè) loader 的抽象基類,它實(shí)現(xiàn)了可選的 PEP 302 協(xié)議用于從存儲(chǔ)后端加載任意資源。
3.7 版后已移除: 由于要支持使用
importlib.abc.ResourceReader
類來(lái)加載資源,這個(gè) ABC 已經(jīng)被棄用了。- abstractmethod get_data(path)?
一個(gè)用于返回位于 path 的字節(jié)數(shù)據(jù)的抽象方法。有一個(gè)允許存儲(chǔ)任意數(shù)據(jù)的類文件存儲(chǔ)后端的加載器能夠?qū)崿F(xiàn)這個(gè)抽象方法來(lái)直接訪問(wèn)這些被存儲(chǔ)的數(shù)據(jù)。如果不能夠找到 path,則會(huì)引發(fā)
OSError
異常。path 被希望使用一個(gè)模塊的__file
屬性或來(lái)自一個(gè)包的__path__
來(lái)構(gòu)建。在 3.4 版更改: 引發(fā)
OSError
異常而不是NotImplementedError
異常。
- class importlib.abc.InspectLoader?
一個(gè)實(shí)現(xiàn)加載器檢查模塊可選的 PEP 302 協(xié)議的 loader 的抽象基類。
- get_code(fullname)?
返回一個(gè)模塊的代碼對(duì)象,或如果模塊沒(méi)有一個(gè)代碼對(duì)象(例如,對(duì)于內(nèi)置的模塊來(lái)說(shuō),這會(huì)是這種情況),則為
None
。 如果加載器不能找到請(qǐng)求的模塊,則引發(fā)ImportError
異常。備注
當(dāng)這個(gè)方法有一個(gè)默認(rèn)的實(shí)現(xiàn)的時(shí)候,出于性能方面的考慮,如果有可能的話,建議覆蓋它。
在 3.4 版更改: 不再抽象并且提供一個(gè)具體的實(shí)現(xiàn)。
- abstractmethod get_source(fullname)?
一個(gè)返回模塊源的抽象方法。使用 universal newlines 作為文本字符串被返回,將所有可識(shí)別行分割符翻譯成
'\n'
字符。 如果沒(méi)有可用的源(例如,一個(gè)內(nèi)置模塊),則返回None
。 如果加載器不能找到指定的模塊,則引發(fā)ImportError
異常。在 3.4 版更改: 引發(fā)
ImportError
而不是NotImplementedError
。
- is_package(fullname)?
可選方法,如果模塊為包,則返回 True,否則返回 False。 如果 loader 找不到模塊,則會(huì)觸發(fā)
ImportError
。在 3.4 版更改: 引發(fā)
ImportError
而不是NotImplementedError
。
- static source_to_code(data, path='<string>')?
創(chuàng)建一個(gè)來(lái)自Python源碼的代碼對(duì)象。
參數(shù) data 可以是任意
compile()
函數(shù)支持的類型(例如字符串或字節(jié)串)。 參數(shù) path 應(yīng)該是源代碼來(lái)源的路徑,這可能是一個(gè)抽象概念(例如位于一個(gè) zip 文件中)。在有后續(xù)代碼對(duì)象的情況下,可以在一個(gè)模塊中通過(guò)運(yùn)行``exec(code, module.__dict__)``來(lái)執(zhí)行它。
3.4 新版功能.
在 3.5 版更改: 使得這個(gè)方法變成靜態(tài)的。
- exec_module(module)?
Loader.exec_module()
的實(shí)現(xiàn)。3.4 新版功能.
- load_module(fullname)?
Loader.load_module()
的實(shí)現(xiàn)。3.4 版后已移除: 使用
exec_module()
來(lái)代替。
- class importlib.abc.ExecutionLoader?
一個(gè)繼承自
InspectLoader
的抽象基類,當(dāng)被實(shí)現(xiàn)時(shí),幫助一個(gè)模塊作為腳本來(lái)執(zhí)行。 這個(gè)抽象基類表示可選的 PEP 302 協(xié)議。- abstractmethod get_filename(fullname)?
一個(gè)用來(lái)為指定模塊返回
__file__
的值的抽象方法。如果無(wú)路徑可用,則引發(fā)ImportError
。如果源代碼可用,那么這個(gè)方法返回源文件的路徑,不管是否是用來(lái)加載模塊的字節(jié)碼。
在 3.4 版更改: 引發(fā)
ImportError
而不是NotImplementedError
。
- class importlib.abc.FileLoader(fullname, path)?
一個(gè)繼承自
ResourceLoader
和ExecutionLoader
,提供ResourceLoader.get_data()
和ExecutionLoader.get_filename()
具體實(shí)現(xiàn)的抽象基類。參數(shù) fullname 是加載器要處理的模塊的完全解析的名字。參數(shù) path 是模塊文件的路徑。
3.3 新版功能.
- name?
加載器可以處理的模塊的名字。
- path?
模塊的文件路徑
- load_module(fullname)?
調(diào)用super的``load_module()``。
3.4 版后已移除: 使用
Loader.exec_module()
來(lái)代替。
- abstractmethod get_data(path)?
讀取 path 作為二進(jìn)制文件并且返回來(lái)自它的字節(jié)數(shù)據(jù)。
- class importlib.abc.SourceLoader?
一個(gè)用于實(shí)現(xiàn)源文件(和可選地字節(jié)碼)加載的抽象基類。這個(gè)類繼承自
ResourceLoader
和ExecutionLoader
,需要實(shí)現(xiàn):ExecutionLoader.get_filename()
應(yīng)該是只返回源文件的路徑;不支持無(wú)源加載。
由這個(gè)類定義的抽象方法用來(lái)添加可選的字節(jié)碼文件支持。不實(shí)現(xiàn)這些可選的方法(或?qū)е滤鼈円l(fā)
NotImplementedError
異常)導(dǎo)致這個(gè)加載器只能與源代碼一起工作。 實(shí)現(xiàn)這些方法允許加載器能與源 和 字節(jié)碼文件一起工作。不允許只提供字節(jié)碼的 無(wú)源式 加載。字節(jié)碼文件是通過(guò)移除 Python 編譯器的解析步驟來(lái)加速加載的優(yōu)化,并且因此沒(méi)有開放出字節(jié)碼專用的 API。- path_stats(path)?
返回一個(gè)包含關(guān)于指定路徑的元數(shù)據(jù)的
dict
的可選的抽象方法。 支持的字典鍵有:'mtime'
(必選項(xiàng)): 一個(gè)表示源碼修改時(shí)間的整數(shù)或浮點(diǎn)數(shù);'size'
(可選項(xiàng)):源碼的字節(jié)大小。
字典中任何其他鍵會(huì)被忽略,以允許將來(lái)的擴(kuò)展。 如果不能處理該路徑,則會(huì)引發(fā)
OSError
。3.3 新版功能.
在 3.4 版更改: 引發(fā)
OSError
而不是NotImplemented
。
- path_mtime(path)?
返回指定文件路徑修改時(shí)間的可選的抽象方法。
3.3 版后已移除: 在有了
path_stats()
的情況下,這個(gè)方法被棄用了。 沒(méi)必要去實(shí)現(xiàn)它了,但是為了兼容性,它依然處于可用狀態(tài)。 如果文件路徑不能被處理,則引發(fā)OSError
異常。在 3.4 版更改: 引發(fā)
OSError
而不是NotImplemented
。
- set_data(path, data)?
往一個(gè)文件路徑寫入指定字節(jié)的的可選的抽象方法。任何中間不存在的目錄不會(huì)被自動(dòng)創(chuàng)建。
由于路徑是只讀的,當(dāng)寫入的路徑產(chǎn)生錯(cuò)誤時(shí)(
errno.EACCES
/PermissionError
),不會(huì)傳播異常。在 3.4 版更改: 當(dāng)被調(diào)用時(shí),不再引起
NotImplementedError
異常。
- get_code(fullname)?
InspectLoader.get_code()
的具體實(shí)現(xiàn)。
- exec_module(module)?
Loader.exec_module()
的具體實(shí)現(xiàn)。3.4 新版功能.
- load_module(fullname)?
Concrete implementation of
Loader.load_module()
.3.4 版后已移除: 使用
exec_module()
來(lái)代替。
- get_source(fullname)?
InspectLoader.get_source()
的具體實(shí)現(xiàn)。
- is_package(fullname)?
InspectLoader.is_package()
的具體實(shí)現(xiàn)。一個(gè)模塊被確定為一個(gè)包的條件是:它的文件路徑(由ExecutionLoader.get_filename()
提供)當(dāng)文件擴(kuò)展名被移除時(shí)是一個(gè)命名為__init__
的文件,并且 這個(gè)模塊名字本身不是以``__init__``結(jié)束。
- class importlib.abc.Traversable?
擁有部分 pathlib.Path 方法的對(duì)象,適用于遍歷目錄和打開文件。
3.9 新版功能.
- name?
Abstract. The base name of this object without any parent references.
- abstractmethod iterdir()?
Yield Traversable objects in self.
- abstractmethod is_dir()?
Return True if self is a directory.
- abstractmethod is_file()?
Return True if self is a file.
- abstractmethod joinpath(child)?
Return Traversable child in self.
- abstractmethod __truediv__(child)?
Return Traversable child in self.
- abstractmethod open(mode='r', *args, **kwargs)?
mode may be 'r' or 'rb' to open as text or binary. Return a handle suitable for reading (same as
pathlib.Path.open
).When opening as text, accepts encoding parameters such as those accepted by
io.TextIOWrapper
.
- read_bytes()?
Read contents of self as bytes.
- read_text(encoding=None)?
Read contents of self as text.
- class importlib.abc.TraversableResources?
An abstract base class for resource readers capable of serving the
importlib.resources.files()
interface. Subclassesimportlib.abc.ResourceReader
and provides concrete implementations of theimportlib.abc.ResourceReader
's abstract methods. Therefore, any loader supplyingimportlib.abc.TraversableReader
also supplies ResourceReader.需要支持資源讀取的加載器應(yīng)實(shí)現(xiàn)此接口。
3.9 新版功能.
- abstractmethod files()?
Returns a
importlib.abc.Traversable
object for the loaded package.
importlib.machinery
—— 導(dǎo)入器和路徑鉤子函數(shù)。?
源代碼: Lib/importlib/machinery.py
本模塊包含多個(gè)對(duì)象,以幫助 import
查找并加載模塊。
- importlib.machinery.SOURCE_SUFFIXES?
一個(gè)字符串列表,表示源模塊的可識(shí)別的文件后綴。
3.3 新版功能.
- importlib.machinery.DEBUG_BYTECODE_SUFFIXES?
一個(gè)字符串列表,表示未經(jīng)優(yōu)化字節(jié)碼模塊的文件后綴。
3.3 新版功能.
3.5 版后已移除: 改用
BYTECODE_SUFFIXES
。
- importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES?
一個(gè)字符串列表,表示已優(yōu)化字節(jié)碼模塊的文件后綴。
3.3 新版功能.
3.5 版后已移除: 改用
BYTECODE_SUFFIXES
。
- importlib.machinery.BYTECODE_SUFFIXES?
一個(gè)字符串列表,表示字節(jié)碼模塊的可識(shí)別的文件后綴(包含前導(dǎo)的句點(diǎn)符號(hào))。
3.3 新版功能.
在 3.5 版更改: 該值不再依賴于
__debug__
。
- importlib.machinery.EXTENSION_SUFFIXES?
一個(gè)字符串列表,表示擴(kuò)展模塊的可識(shí)別的文件后綴。
3.3 新版功能.
- importlib.machinery.all_suffixes()?
返回字符串的組合列表,代表標(biāo)準(zhǔn)導(dǎo)入機(jī)制可識(shí)別模塊的所有文件后綴。這是個(gè)助手函數(shù),只需知道某個(gè)文件系統(tǒng)路徑是否會(huì)指向模塊,而不需要任何關(guān)于模塊種類的細(xì)節(jié)(例如
inspect.getmodulename()
)。3.3 新版功能.
- class importlib.machinery.BuiltinImporter?
用于導(dǎo)入內(nèi)置模塊的 importer。 所有已知的內(nèi)置模塊都已列入
sys.builtin_module_names
。 此類實(shí)現(xiàn)了importlib.abc.MetaPathFinder
和importlib.abc.InspectLoader
抽象基類。此類只定義類的方法,以減輕實(shí)例化的開銷。
在 3.5 版更改: 作為 PEP 489 的一部分,現(xiàn)在內(nèi)置模塊導(dǎo)入器實(shí)現(xiàn)了
Loader.create_module()
和Loader.exec_module()
。
- class importlib.machinery.FrozenImporter?
用于已凍結(jié)模塊的 importer。 此類實(shí)現(xiàn)了
importlib.abc.MetaPathFinder
和importlib.abc.InspectLoader
抽象基類。此類只定義類的方法,以減輕實(shí)例化的開銷。
在 3.4 版更改: 有了
create_module()
和exec_module()
方法。
- class importlib.machinery.WindowsRegistryFinder?
Finder 用于查找在 Windows 注冊(cè)表中聲明的模塊。該類實(shí)現(xiàn)了基礎(chǔ)的
importlib.abc.MetaPathFinder
。此類只定義類的方法,以減輕實(shí)例化的開銷。
3.3 新版功能.
3.6 版后已移除: 改用
site
配置。未來(lái)版本的 Python 可能不會(huì)默認(rèn)啟用該查找器。
- class importlib.machinery.PathFinder?
用于
sys.path
和包的__path__
屬性的 Finder 。該類實(shí)現(xiàn)了基礎(chǔ)的importlib.abc.MetaPathFinder
。此類只定義類的方法,以減輕實(shí)例化的開銷。
- classmethod find_spec(fullname, path=None, target=None)?
類方法試圖在
sys.path
或 path 上為 fullname 指定的模塊查找 spec。對(duì)于每個(gè)路徑條目,都會(huì)查看sys.path_importer_cache
。如果找到非 False 的對(duì)象,則將其用作 path entry finder 來(lái)查找要搜索的模塊。如果在sys.path_importer_cache
中沒(méi)有找到條目,那會(huì)在sys.path_hooks
檢索該路徑條目的查找器,找到了則和查到的模塊信息一起存入sys.path_importer_cache
。如果查找器沒(méi)有找到,則緩存中的查找器和模塊信息都存為None
,然后返回。3.4 新版功能.
在 3.5 版更改: 如果當(dāng)前工作目錄不再有效(用空字符串表示),則返回
None
,但在sys.path_importer_cache
中不會(huì)有緩存值。
- classmethod find_module(fullname, path=None)?
一個(gè)過(guò)時(shí)的
find_spec()
封裝對(duì)象。3.4 版后已移除: 使用
find_spec()
來(lái)代替。
- 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
中的對(duì)象,當(dāng)前工作目錄為''
(即空字符串)。
- class importlib.machinery.FileFinder(path, *loader_details)?
importlib.abc.PathEntryFinder
的一個(gè)具體實(shí)現(xiàn),它會(huì)緩存來(lái)自文件系統(tǒng)的結(jié)果。參數(shù) path 是查找器負(fù)責(zé)搜索的目錄。
loader_details 參數(shù)是數(shù)量不定的二元組,每個(gè)元組包含加載器及其可識(shí)別的文件后綴列表。加載器應(yīng)為可調(diào)用對(duì)象,可接受兩個(gè)參數(shù),即模塊的名稱和已找到文件的路徑。
查找器將按需對(duì)目錄內(nèi)容進(jìn)行緩存,通過(guò)對(duì)每個(gè)模塊的檢索進(jìn)行狀態(tài)統(tǒng)計(jì),驗(yàn)證緩存是否過(guò)期。因?yàn)榫彺娴臏笮砸蕾囉诓僮飨到y(tǒng)文件系統(tǒng)狀態(tài)信息的粒度,所以搜索模塊、新建文件、然后搜索新文件代表的模塊,這會(huì)存在競(jìng)爭(zhēng)狀態(tài)。如果這些操作的頻率太快,甚至小于狀態(tài)統(tǒng)計(jì)的粒度,那么模塊搜索將會(huì)失敗。為了防止這種情況發(fā)生,在動(dòng)態(tài)創(chuàng)建模塊時(shí),請(qǐng)確保調(diào)用
importlib.invalidate_caches()
。3.3 新版功能.
- path?
查找器將要搜索的路徑。
- find_loader(fullname)?
試圖在
path
內(nèi)找到處理 fullname 的加載器。3.10 版后已移除: 使用
find_spec()
來(lái)代替。
- invalidate_caches()?
清理內(nèi)部緩存。
- classmethod path_hook(*loader_details)?
一個(gè)類方法,返回供
sys.path_hooks
使用的閉包。根據(jù)直接給出的路徑參數(shù)和間接給出的 loader_details,閉包會(huì)返回一個(gè)FileFinder
的實(shí)例。如果給閉包的參數(shù)不是已存在的目錄,將會(huì)觸發(fā)
ImportError
。
- class importlib.machinery.SourceFileLoader(fullname, path)?
importlib.abc.SourceLoader
的一個(gè)具體實(shí)現(xiàn),該實(shí)現(xiàn)子類化了importlib.abc.FileLoader
并提供了其他一些方法的具體實(shí)現(xiàn)。3.3 新版功能.
- name?
該加載器將要處理的模塊名稱。
- path?
源文件的路徑
- path_stats(path)?
importlib.abc.SourceLoader.path_stats()
的具體代碼實(shí)現(xiàn)。
- set_data(path, data)?
importlib.abc.SourceLoader.set_data()
的具體代碼實(shí)現(xiàn)。
- load_module(name=None)?
importlib.abc.Loader.load_module()
的具體代碼實(shí)現(xiàn),這里要加載的模塊名是可選的。3.6 版后已移除: 改用
importlib.abc.Loader.exec_module()
。
- class importlib.machinery.SourcelessFileLoader(fullname, path)?
importlib.abc.FileLoader
的具體代碼實(shí)現(xiàn),可導(dǎo)入字節(jié)碼文件(也即源代碼文件不存在)。請(qǐng)注意,直接用字節(jié)碼文件(而不是源代碼文件),會(huì)讓模塊無(wú)法應(yīng)用于所有的 Python 版本或字節(jié)碼格式有所改動(dòng)的新版本 Python。
3.3 新版功能.
- name?
加載器將要處理的模塊名。
- path?
二進(jìn)制碼文件的路徑。
- get_source(fullname)?
因?yàn)橛么思虞d器時(shí)字節(jié)碼文件沒(méi)有源碼文件,所以返回
None
。
- load_module(name=None)?
importlib.abc.Loader.load_module()
的具體代碼實(shí)現(xiàn),這里要加載的模塊名是可選的。3.6 版后已移除: 改用
importlib.abc.Loader.exec_module()
。
- class importlib.machinery.ExtensionFileLoader(fullname, path)?
importlib.abc.ExecutionLoader
的具體代碼實(shí)現(xiàn),用于擴(kuò)展模塊。參數(shù) fullname 指定了加載器要支持的模塊名。參數(shù) path 是指向擴(kuò)展模塊文件的路徑。
3.3 新版功能.
- name?
裝載器支持的模塊名。
- path?
擴(kuò)展模塊的路徑。
- is_package(fullname)?
根據(jù)
EXTENSION_SUFFIXES
,如果文件路徑指向某個(gè)包的__init__
模塊,則返回True
。
- get_code(fullname)?
返回
None
,因?yàn)閿U(kuò)展模塊缺少代碼對(duì)象。
- get_source(fullname)?
返回
None
,因?yàn)閿U(kuò)展模塊沒(méi)有源代碼。
- NamespaceLoader(name, path, path_finder):
A concrete implementation of
importlib.abc.InspectLoader
for namespace packages. This is an alias for a private class and is only made public for introspecting the__loader__
attribute on namespace packages:>>> 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)?
A specification for a module's import-system-related state. This is typically exposed as the module's
__spec__
attribute. In the descriptions below, the names in parentheses give the corresponding attribute available directly on the module object, e.g.module.__spec__.origin == module.__file__
. Note, however, that while the values are usually equivalent, they can differ since there is no synchronization between the two objects. For example, it is possible to update the module's__file__
at runtime and this will not be automatically reflected in the module's__spec__.origin
, and vice versa.3.4 新版功能.
- name?
(
__name__
)The module's fully-qualified name. The finder should always set this attribute to a non-empty string.
- loader?
The loader used to load the module. The finder should always set this attribute.
- origin?
(
__file__
)The location the loader should use to load the module. For example, for modules loaded from a .py file this is the filename. The finder should always set this attribute to a meaningful value for the loader to use. In the uncommon case that there is not one (like for namespace packages), it should be set to
None
.- submodule_search_locations?
(
__path__
)The list of locations where the package's submodules will be found. Most of the time this is a single directory. The finder should set this attribute to a list, even an empty one, to indicate to the import system that the module is a package. It should be set to
None
for non-package modules. It is set automatically later to a special object for namespace packages.- loader_state?
The finder may set this attribute to an object containing additional, module-specific data to use when loading the module. Otherwise it should be set to
None
.- cached?
The filename of a compiled version of the module's code. The finder should always set this attribute but it may be
None
for modules that do not need compiled code stored.- parent?
(Read-only) The fully-qualified name of the package the module is in (or the empty string for a top-level module). If the module is a package then this is the same as
name
.- has_location?
importlib.util
—— 導(dǎo)入器的工具程序代碼?
本模塊包含了幫助構(gòu)建 importer 的多個(gè)對(duì)象。
- importlib.util.MAGIC_NUMBER?
代表字節(jié)碼版本號(hào)的字節(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
來(lái)自于當(dāng)前的魔法標(biāo)簽 (參見(jiàn)get_tag()
; 如果sys.implementation.cache_tag
未定義則將會(huì)引發(fā)NotImplementedError
)。參數(shù) optimization 用于指定字節(jié)碼文件的優(yōu)化級(jí)別??兆址頉](méi)有優(yōu)化,所以 optimization 為 的
/foo/bar/baz.py
,將會(huì)得到字節(jié)碼路徑為/foo/bar/__pycache__/baz.cpython-32.pyc
。None
會(huì)導(dǎo)致采用解釋器的優(yōu)化。任何其他字符串都會(huì)被采用,所以 optimization 為''
的/foo/bar/baz.py
會(huì)導(dǎo)致字節(jié)碼路徑為/foo/bar/__pycache__/baz.cpython-32.opt-2.pyc
。optimization 字符串只能是字母數(shù)字,否則會(huì)觸發(fā)ValueError
。debug_override 參數(shù)已廢棄,可用于覆蓋系統(tǒng)的
__debug__
值。True
值相當(dāng)于將 optimization 設(shè)為空字符串。False
則相當(dāng)于*optimization* 設(shè)為1
。如果 debug_override 和 optimization 都不為None
,則會(huì)觸發(fā)TypeError
。3.4 新版功能.
在 3.5 版更改: 增加了 optimization 參數(shù),廢棄了 debug_override 參數(shù)。
在 3.6 版更改: 接受一個(gè) path-like object。
- importlib.util.source_from_cache(path)?
根據(jù)指向一個(gè) PEP 3147 文件名的 path,返回相關(guān)聯(lián)的源代碼文件路徑。 舉例來(lái)說(shuō),如果 path 為
/foo/bar/__pycache__/baz.cpython-32.pyc
則返回的路徑將是/foo/bar/baz.py
。 path 不需要已存在,但如果它未遵循 PEP 3147 或 PEP 488 的格式,則會(huì)引發(fā)ValueError
。 如果未定義sys.implementation.cache_tag
,則會(huì)引發(fā)NotImplementedError
。3.4 新版功能.
在 3.6 版更改: 接受一個(gè) path-like object。
- importlib.util.decode_source(source_bytes)?
對(duì)代表源代碼的字節(jié)串進(jìn)行解碼,并將其作為帶有通用換行符的字符串返回(符合
importlib.abc.InspectLoader.get_source()
要求)。3.4 新版功能.
- importlib.util.resolve_name(name, package)?
將模塊的相對(duì)名稱解析為絕對(duì)名稱。
如果 name 前面沒(méi)有句點(diǎn),那就簡(jiǎn)單地返回 name。這樣就能采用``importlib.util.resolve_name('sys', __spec__.parent)`` 之類的寫法,而無(wú)需檢查是否需要 package 參數(shù)。
ImportError
is raised if name is a relative module name but package is a false value (e.g.None
or the empty string).ImportError
is also raised if a relative name would escape its containing package (e.g. requesting..bacon
from within thespam
package).3.3 新版功能.
在 3.9 版更改: 為了改善與 import 語(yǔ)句的一致性,對(duì)于無(wú)效的相對(duì)導(dǎo)入嘗試會(huì)引發(fā)
ImportError
而不是ValueError
。
- importlib.util.find_spec(name, package=None)?
查找模塊的 spec,相對(duì)指定的 package 名為可選參數(shù)。如果該模塊位于
sys.modules
中,則會(huì)返回sys.modules[name].__spec__
(除非 spec為None
或未作設(shè)置,這時(shí)會(huì)觸發(fā)ValueError
)。否則將用sys.meta_path
進(jìn)行搜索。若找不到則返回None
。如果 name 為一個(gè)子模塊(帶有一個(gè)句點(diǎn)),則會(huì)自動(dòng)導(dǎo)入父級(jí)模塊。
name 和 package 的用法與
import_module()
相同。3.4 新版功能.
在 3.7 版更改: 如果 package 實(shí)際上不是一個(gè)包(即缺少
__path__
屬性)則會(huì)引發(fā)ModuleNotFoundError
而不是AttributeError
。
- importlib.util.module_from_spec(spec)?
基于 spec 和
spec.loader.create_module
創(chuàng)建一個(gè)新模塊。如果
spec.loader.create_module
未返回None
,那么先前已存在的屬性不會(huì)被重置。另外,如果AttributeError
是在訪問(wèn) spec 或設(shè)置模塊屬性時(shí)觸發(fā)的,則不會(huì)觸發(fā) 。本函數(shù)比
types.ModuleType
創(chuàng)建新模塊要好,因?yàn)橛玫?spec 模塊設(shè)置了盡可能多的導(dǎo)入控制屬性。3.5 新版功能.
- @importlib.util.module_for_loader?
importlib.abc.Loader.load_module()
的一個(gè) decorator,用來(lái)選取合適的模塊對(duì)象以供加載。被裝飾方法的簽名應(yīng)帶有兩個(gè)位置參數(shù)(如:load_module(self, module)
),其中第二個(gè)參數(shù)將是加載器用到的模塊 對(duì)象。請(qǐng)注意,由于假定有兩個(gè)參數(shù),所以裝飾器對(duì)靜態(tài)方法不起作用。裝飾的方法將接受要加載的模塊的 name,正如 loader 一樣。如果在
sys.modules
中沒(méi)有找到該模塊,那么將構(gòu)造一個(gè)新模塊。不管模塊來(lái)自哪里,__loader__
設(shè)置為 self ,并且__package__
是根據(jù)importlib.abc.InspectLoader.is_package()
的返回值設(shè)置的。這些屬性會(huì)無(wú)條件進(jìn)行設(shè)置以便支持再次加載。如果被裝飾的方法觸發(fā)異常,并且已有模塊加入
sys.modules
中,那么該模塊將被移除,以防sys.modules
中殘留一個(gè)部分初始化的模塊。如果該模塊原先已在sys.modules
中,則會(huì)保留不變。在 3.3 版更改: 有可能時(shí)自動(dòng)設(shè)置
__loader__
和__package__
。在 3.4 版更改: 無(wú)條件設(shè)置
__name__
、__loader__
、__package__
以支持再次加載。3.4 版后已移除: 現(xiàn)在,導(dǎo)入機(jī)制直接執(zhí)行本函數(shù)提供的所有功能。
- @importlib.util.set_loader?
一個(gè) decorator,用于
importlib.abc.Loader.load_module()
在返回的模塊上設(shè)置__loader__
屬性。如果該屬性已被設(shè)置,裝飾器就什么都不做。這里假定被封裝方法的第一個(gè)位置參數(shù)(即self
)就是__loader__
要設(shè)置的。在 3.4 版更改: 如果設(shè)為
None
,則會(huì)去設(shè)置__loader__
,就像該屬性不存在一樣。3.4 版后已移除: 現(xiàn)在導(dǎo)入機(jī)制會(huì)自動(dòng)用到本方法。
- @importlib.util.set_package?
一個(gè)用于
importlib.abc.Loader.load_module()
的 decorator ,以便設(shè)置返回模塊的__package__
屬性。如果__package__
已設(shè)置且不為None
,則不會(huì)做改動(dòng)。3.4 版后已移除: 現(xiàn)在導(dǎo)入機(jī)制會(huì)自動(dòng)用到本方法。
- importlib.util.spec_from_loader(name, loader, *, origin=None, is_package=None)?
一個(gè)工廠函數(shù),用于創(chuàng)建基于加載器的
ModuleSpec
實(shí)例。參數(shù)的含義與 ModuleSpec 的相同。該函數(shù)會(huì)利用當(dāng)前可用的 loader API,比如InspectLoader.is_package()
,以填充所有缺失的規(guī)格信息。3.4 新版功能.
- importlib.util.spec_from_file_location(name, location, *, loader=None, submodule_search_locations=None)?
一個(gè)工廠函數(shù),根據(jù)文件路徑創(chuàng)建
ModuleSpec
實(shí)例。缺失的信息將根據(jù) spec 進(jìn)行填補(bǔ),利用加載器 API ,以及模塊基于文件的隱含條件。3.4 新版功能.
在 3.6 版更改: 接受一個(gè) path-like object。
- importlib.util.source_hash(source_bytes)?
以字節(jié)串的形式返回 source_bytes 的哈希值?;诠V档?
.pyc
文件在頭部嵌入了對(duì)應(yīng)源文件內(nèi)容的source_hash()
。3.7 新版功能.
- class importlib.util.LazyLoader(loader)?
此類會(huì)延遲執(zhí)行模塊加載器,直至該模塊有一個(gè)屬性被訪問(wèn)到。
此類 只 適用于定義了
exec_module()
的加載器,因?yàn)樾枰刂颇K的類型。 同理,加載器的create_module()
方法必須返回None
或__class__
屬性可被改變且不用 slots 的類型。 最后,用于替換sys.modules
內(nèi)容的模塊將無(wú)法工作,因?yàn)闊o(wú)法在整個(gè)解釋器中安全地替換模塊的引用;如果檢測(cè)到這種替換,將觸發(fā)ValueError
。備注
如果項(xiàng)目對(duì)啟動(dòng)時(shí)間要求很高,只要模塊未被用過(guò),此類能夠最小化加載模塊的開銷。對(duì)于啟動(dòng)時(shí)間并不重要的項(xiàng)目來(lái)說(shuō),由于加載過(guò)程中產(chǎn)生的錯(cuò)誤信息會(huì)被暫時(shí)擱置,因此強(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)用對(duì)象。就是說(shuō)用在加載器用類而不是實(shí)例傳遞的場(chǎng)合。
suffixes = importlib.machinery.SOURCE_SUFFIXES loader = importlib.machinery.SourceFileLoader lazy_loader = importlib.util.LazyLoader.factory(loader) finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))
例子?
用編程方式導(dǎo)入?
要以編程方式導(dǎo)入一個(gè)模塊,請(qǐng)使用 importlib.import_module()
:
import importlib
itertools = importlib.import_module('itertools')
檢查某模塊可否導(dǎo)入。?
If you need to find out if a module can be imported without actually doing the
import, then you should use importlib.util.find_spec()
.
Note that if name
is a submodule (contains a dot),
importlib.util.find_spec()
will import the parent module.
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")
直接導(dǎo)入源碼文件。?
To import a Python source file directly, use the following recipe:
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)
sys.modules[module_name] = module
spec.loader.exec_module(module)
實(shí)現(xiàn)延遲導(dǎo)入?
以下例子展示了如何實(shí)現(xiàn)延遲導(dǎo)入:
>>> 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
導(dǎo)入器的配置?
對(duì)于深度定制的導(dǎo)入,通常需要實(shí)現(xiàn)一個(gè) importer。 這意味著得同時(shí)管理 finder 和 loader。 根據(jù)不同的需求,有兩種類型的查找器可供選擇: meta path finder 或 path entry finder。 前者應(yīng)位于 sys.meta_path
之上,而后者是用 path entry hook 在 sys.path_hooks
上創(chuàng)建但與 sys.path
一起工作,可能會(huì)創(chuàng)建一個(gè)查找器。以下例子將演示如何注冊(cè)自己的導(dǎo)入器,以供導(dǎo)入使用(關(guān)于自建導(dǎo)入器請(qǐng)閱讀本包內(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()
的近似實(shí)現(xiàn)?
Import itself is implemented in Python code, making it possible to
expose most of the import machinery through importlib. The following
helps illustrate the various APIs that importlib exposes by providing an
approximate implementation of
importlib.import_module()
:
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