北京市工程建設(shè)信息網(wǎng)官網(wǎng)寧波網(wǎng)站推廣優(yōu)化哪家正規(guī)
3.1 新版功能.
源代碼?Lib/importlib/__init__.py
概述
importlib?包具有三重目標(biāo)。
一是在 Python 源代碼中提供?import?語句的實(shí)現(xiàn)(并且因此而擴(kuò)展?__import__()?函數(shù))。 這提供了一個(gè)可移植到任何 Python 解釋器的?import
?實(shí)現(xiàn)。 與使用 Python 以外的編程語言實(shí)現(xiàn)的方式相比這一實(shí)現(xiàn)也更易于理解。
第二個(gè)目的是實(shí)現(xiàn)?import?的部分被公開在這個(gè)包中,使得用戶更容易創(chuàng)建他們自己的自定義對(duì)象 (通常被稱為?importer) 來參與到導(dǎo)入過程中。
三,這個(gè)包也包含了對(duì)外公開用于管理 Python 包的各個(gè)方面的附加功能的模塊:
-
importlib.metadata?代表對(duì)來自第三方發(fā)行版的元數(shù)據(jù)的訪問。
-
importlib.resources?提供了用于對(duì)來自 Python 包的非代碼“資源”的訪問的例程。
參見
import 語句
import?語句的語言參考
包規(guī)格說明
包的初始規(guī)范。自從編寫這個(gè)文檔開始,一些語義已經(jīng)發(fā)生改變了(比如基于?sys.modules?中?None
?的重定向)。
__import__()?函數(shù)
import?語句是這個(gè)函數(shù)的語法糖。
sys.path 模塊搜索路徑的初始化
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 倉庫目錄
函數(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)入的方式來指定,那么?package?參數(shù)必須設(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ù)的所有語義都來自于?importlib.__import__()。 這兩個(gè)函數(shù)之間最重要的不同點(diǎn)在于?import_module()?返回指定的包或模塊 (例如?pkg.mod
),而?__import__()?返回最高層級(jí)的包或模塊 (例如?pkg
)。
如果動(dòng)態(tài)導(dǎo)入一個(gè)自解釋器開始執(zhí)行以來被創(chuàng)建的模塊(即創(chuàng)建了一個(gè) Python 源代碼文件),為了讓導(dǎo)入系統(tǒng)知道這個(gè)新模塊,可能需要調(diào)用?invalidate_caches()。
在 3.3 版更改:?父包會(huì)被自動(dòng)導(dǎo)入。
importlib.invalidate_caches()
使查找器存儲(chǔ)在?sys.meta_path?中的內(nèi)部緩存無效。如果一個(gè)查找器實(shí)現(xiàn)了?invalidate_caches()
,那么它會(huì)被調(diào)用來執(zhí)行那個(gè)無效過程。 如果創(chuàng)建/安裝任何模塊,同時(shí)正在運(yùn)行的程序是為了保證所有的查找器知道新模塊的存在,那么應(yīng)該調(diào)用這個(gè)函數(shù)。
3.3 新版功能.
在 3.10 版更改:?當(dāng)注意到相同命名空間已被導(dǎo)入之后在不同?sys.path?位置中創(chuàng)建/安裝的命名空間包。
importlib.reload(module)
重新加載之前導(dǎo)入的?module。 那個(gè)參數(shù)必須是一個(gè)模塊對(duì)象,所以它之前必須已經(jīng)成功導(dǎo)入了。 這在你已經(jīng)使用外部編輯器編輯過了那個(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í)行,通過重新使用一開始加載那個(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ì)覆蓋舊的定義,所以通常來說這不是問題。如果一個(gè)新模塊沒有定義在舊版本模塊中定義的名稱,則將保留舊版本中的定義。這一特性可用于作為那個(gè)模塊的優(yōu)點(diǎn),如果它維護(hù)一個(gè)全局表或者對(duì)象的緩存 —— 使用?try?語句,就可以測(cè)試表的存在并且跳過它的初始化,如果有需要的話:
try:cache except NameError:cache = {}
重新加載內(nèi)置的或者動(dòng)態(tài)加載模塊,通常來說不是很有用處。不推薦重新加載"sys,__main__,builtins?和其它關(guān)鍵模塊。在很多例子中,擴(kuò)展模塊并不是設(shè)計(jì)為不止一次的初始化,并且當(dāng)重新加載時(shí),可能會(huì)以任意方式失敗。
如果一個(gè)模塊使用?from?...?import?... 導(dǎo)入的對(duì)象來自另外一個(gè)模塊,給其它模塊調(diào)用?reload()?不會(huì)重新定義來自這個(gè)模塊的對(duì)象 —— 解決這個(gè)問題的一種方式是重新執(zhí)行?from
?語句,另一種方式是使用?import
?和限定名稱(module.name)來代替。
如果一個(gè)模塊創(chuàng)建一個(gè)類的實(shí)例,重新加載定義那個(gè)類的模塊不影響那些實(shí)例的方法定義———它們繼續(xù)使用舊類中的定義。對(duì)于子類來說同樣是正確的。
3.4 新版功能.
在 3.7 版更改:?如果重新加載的模塊缺少?ModuleSpec?,則會(huì)觸發(fā)?ModuleNotFoundError?。
importlib.abc?—— 關(guān)于導(dǎo)入的抽象基類
源代碼:?Lib/importlib/abc.py
importlib.abc?模塊包含了?import?使用到的所有核心抽象基類。在實(shí)現(xiàn)核心的 ABCs 中,核心抽象基類的一些子類也提供了幫助。
ABC 類的層次結(jié)構(gòu):
object+-- MetaPathFinder+-- PathEntryFinder+-- Loader+-- ResourceLoader --------++-- InspectLoader |+-- ExecutionLoader --++-- FileLoader+-- SourceLoader
class?importlib.abc.MetaPathFinder
一個(gè)代表?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ì)象,查找器可以用來對(duì)返回的規(guī)格進(jìn)行更有依據(jù)的猜測(cè)。在實(shí)現(xiàn)具體的?MetaPathFinders
?代碼時(shí),可能會(huì)用到?importlib.util.spec_from_loader()?。
3.4 新版功能.
invalidate_caches()
當(dāng)被調(diào)用的時(shí)候,一個(gè)可選的方法應(yīng)該將查找器使用的任何內(nèi)部緩存進(jìn)行無效。將在?sys.meta_path?上的所有查找器的緩存進(jìn)行無效的時(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 新版功能.
invalidate_caches()
可選方法,調(diào)用后應(yīng)讓查找器用到的所有內(nèi)部緩存失效。要讓所有緩存的查找器的緩存無效時(shí),可供?importlib.machinery.PathFinder.invalidate_caches()?調(diào)用。
class?importlib.abc.Loader
loader?的抽象基類。 關(guān)于一個(gè)加載器的實(shí)際定義請(qǐng)查看?PEP 302。
想要支持資源讀取的加載器應(yīng)當(dāng)實(shí)現(xiàn)?importlib.resources.abc.ResourceReader?所規(guī)定的?get_resource_reader()
?方法。
在 3.7 版更改:?引入了可選的?get_resource_reader()
?方法。
create_module(spec)
當(dāng)導(dǎo)入一個(gè)模塊的時(shí)候,一個(gè)返回將要使用的那個(gè)模塊對(duì)象的方法。這個(gè)方法可能返回?None
?,這暗示著應(yīng)該發(fā)生默認(rèn)的模塊創(chuàng)建語義。"
3.4 新版功能.
在 3.6 版更改:?當(dāng)?exec_module()?已定義時(shí)此方法將不再是可選項(xiàng)。
exec_module(module)
當(dāng)一個(gè)模塊被導(dǎo)入或重新加載時(shí)在自己的命名空間中執(zhí)行該模塊的的抽象方法。 該模塊在?exec_module()?被調(diào)用時(shí)應(yīng)該已經(jīng)被初始化了。 當(dāng)此方法存在時(shí),必須要定義?create_module()。
3.4 新版功能.
在 3.6 版更改:?create_module()?也必須要定義。
load_module(fullname)
用于加載模塊的傳統(tǒng)方法。 如果模塊無法被導(dǎo)入,則會(huì)引發(fā)?ImportError,在其他情況下將返回被加載的模塊。
如果請(qǐng)求的模塊已存在于?sys.modules?中,則該模塊應(yīng)當(dāng)被使用并重新加載。 在其他情況下加載器應(yīng)當(dāng)創(chuàng)建一個(gè)新模塊并在任何加載操作開始之前將其插入到?sys.modules?中,以防止來自導(dǎo)入的無限遞歸。 如果加載器插入了一個(gè)模塊并且加載失敗,則必須用加載器將其從?sys.modules?中移除;在加載器開始執(zhí)行之前已經(jīng)存在于?sys.modules?中的模塊應(yīng)當(dāng)保持原樣。
加載器應(yīng)當(dāng)在模塊上設(shè)置幾個(gè)屬性(請(qǐng)注意在模塊被重新加載時(shí)這些屬性有幾個(gè)可能發(fā)生改變):
-
__name__
模塊的完整限定名稱。 對(duì)于被執(zhí)行的模塊來說是?
'__main__'
。 -
__file__
被?loader?用于加載指定模塊的位置。 例如,對(duì)于從一個(gè) .py 文件加載的模塊來說即文件名。 這不一定會(huì)在所有模塊上設(shè)置(例如內(nèi)置模塊就不會(huì)設(shè)置)。
-
__cached__
模塊代碼的編譯版本的文件名。 這不一定會(huì)在所有模塊上設(shè)置(例如內(nèi)置模塊就不會(huì)設(shè)置)。
-
__path__
用于查找指定包的子模塊的位置列表。 在大多數(shù)時(shí)候這將為單個(gè)目錄。 導(dǎo)入系統(tǒng)會(huì)以與?sys.path?相同但專門針對(duì)指定包的方式將此屬性傳給?
__import__()
?和查找器。 這不會(huì)在非包模塊上設(shè)置因此它可以被用作確定模塊是否為包的指示器。 -
__package__
指定模塊所在包的完整限定名稱(或者對(duì)于最高層級(jí)模塊來說則為空字符串)。 如果模塊是包則它將與?__name__?相同。
-
__loader__
用于加載模塊的?loader。
當(dāng)?exec_module()?可用的時(shí)候,那么則提供了向后兼容的功能。
在 3.4 版更改:?當(dāng)被調(diào)用時(shí)將引發(fā)?ImportError?而不是?NotImplementedError。 在?exec_module()?可用時(shí)提供的功能。
3.4 版后已移除:?用于加載模塊的推薦 API 是?exec_module()?(和?create_module())。 加載器應(yīng)該實(shí)現(xiàn)它而不是?load_module()。 當(dāng)實(shí)現(xiàn)了?exec_module()?時(shí)導(dǎo)入機(jī)制將會(huì)承擔(dān)?load_module()?的所有其他責(zé)任。
class?importlib.abc.ResourceLoader
一個(gè)?loader?的抽象基類,它實(shí)現(xiàn)了可選的?PEP 302?協(xié)議用于從存儲(chǔ)后端加載任意資源。
3.7 版后已移除:?這個(gè) ABC 已被棄用并轉(zhuǎn)為通過?importlib.resources.abc.ResourceReader?來支持資源加載。
abstractmethod?get_data(path)
一個(gè)用于返回位于?path?的字節(jié)數(shù)據(jù)的抽象方法。有一個(gè)允許存儲(chǔ)任意數(shù)據(jù)的類文件存儲(chǔ)后端的加載器能夠?qū)崿F(xiàn)這個(gè)抽象方法來直接訪問這些被存儲(chǔ)的數(shù)據(jù)。如果不能夠找到?path,則會(huì)引發(fā)?OSError?異常。path?被希望使用一個(gè)模塊的?__file
?屬性或來自一個(gè)包的?__path__?來構(gòu)建。
在 3.4 版更改:?引發(fā)?OSError?異常而不是?NotImplementedError?異常。
class?importlib.abc.InspectLoader
一個(gè)實(shí)現(xiàn)加載器檢查模塊可選的?PEP 302?協(xié)議的?loader?的抽象基類。
get_code(fullname)
返回一個(gè)模塊的代碼對(duì)象,或如果模塊沒有一個(gè)代碼對(duì)象(例如,對(duì)于內(nèi)置的模塊來說,這會(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'
?字符。 如果沒有可用的源(例如,一個(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è)來自Python源碼的代碼對(duì)象。
參數(shù)?data?可以是任意?compile()?函數(shù)支持的類型(例如字符串或字節(jié)串)。 參數(shù)?path?應(yīng)該是源代碼來源的路徑,這可能是一個(gè)抽象概念(例如位于一個(gè) zip 文件中)。
在有后續(xù)代碼對(duì)象的情況下,可以在一個(gè)模塊中通過運(yùn)行?exec(code,?module.__dict__)
?來執(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()?來代替。
class?importlib.abc.ExecutionLoader
一個(gè)繼承自?InspectLoader?的抽象基類,當(dāng)被實(shí)現(xiàn)時(shí),幫助一個(gè)模塊作為腳本來執(zhí)行。 這個(gè)抽象基類表示可選的?PEP 302?協(xié)議。
abstractmethod?get_filename(fullname)
一個(gè)用來為指定模塊返回?__file__?的值的抽象方法。如果無路徑可用,則引發(fā)?ImportError。
如果源代碼可用,那么這個(gè)方法返回源文件的路徑,不管是否是用來加載模塊的字節(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()?來代替。
abstractmethod?get_filename(fullname)
返回?path。
abstractmethod?get_data(path)
讀取?path?作為二進(jìn)制文件并且返回來自它的字節(jié)數(shù)據(jù)。
class?importlib.abc.SourceLoader
一個(gè)用于實(shí)現(xiàn)源文件(和可選地字節(jié)碼)加載的抽象基類。這個(gè)類繼承自?ResourceLoader?和?ExecutionLoader,需要實(shí)現(xiàn):
-
ResourceLoader.get_data()
-
ExecutionLoader.get_filename()
應(yīng)該是只返回源文件的路徑;不支持無源加載。
由這個(gè)類定義的抽象方法用來添加可選的字節(jié)碼文件支持。不實(shí)現(xiàn)這些可選的方法(或?qū)е滤鼈円l(fā)?NotImplementedError?異常)導(dǎo)致這個(gè)加載器只能與源代碼一起工作。 實(shí)現(xiàn)這些方法允許加載器能與源?和?字節(jié)碼文件一起工作。不允許只提供字節(jié)碼的?無源式?加載。字節(jié)碼文件是通過移除 Python 編譯器的解析步驟來加速加載的優(yōu)化,并且因此沒有開放出字節(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ì)被忽略,以允許將來的擴(kuò)展。 如果不能處理該路徑,則會(huì)引發(fā)?OSError。
3.3 新版功能.
在 3.4 版更改:?引發(fā)?OSError?而不是?NotImplemented。
path_mtime(path)
返回指定文件路徑修改時(shí)間的可選的抽象方法。
3.3 版后已移除:?在有了?path_stats()?的情況下,這個(gè)方法被棄用了。 沒必要去實(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)對(duì)路徑的寫入因路徑為只讀而失敗時(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()?來代替。
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.ResourceReader
被 TraversableResources?取代
提供讀取?resources?能力的一個(gè)?abstract base class?。
從這個(gè) ABC 的視角出發(fā),resource?指一個(gè)包附帶的二進(jìn)制文件。常見的如在包的?__init__.py
?文件旁的數(shù)據(jù)文件。這個(gè)類存在的目的是為了將對(duì)數(shù)據(jù)文件的訪問進(jìn)行抽象,這樣包就和其數(shù)據(jù)文件的存儲(chǔ)方式無關(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)
?方法。如果通過全名指定的模塊不是一個(gè)包,這個(gè)方法應(yīng)該返回?None。 當(dāng)指定的模塊是一個(gè)包時(shí),應(yīng)該只返回一個(gè)與這個(gè)抽象類ABC兼容的對(duì)象。
3.7 新版功能.
從 3.12 版起不建議使用,將在 3.14 版中移除:?使用?importlib.resources.abc.TraversableResources?代替。
abstractmethod?open_resource(resource)
返回一個(gè)打開的?file-like object?用于?resource?的二進(jìn)制讀取。
如果無法找到資源,將會(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.Traversable
一個(gè)具有?pathlib.Path?中方法的子集并適用于遍歷目錄和打開文件的對(duì)象。
對(duì)于該對(duì)象在文件系統(tǒng)中的表示形式,請(qǐng)使用?importlib.resources.as_file()。
3.9 新版功能.
從 3.12 版起不建議使用,將在 3.14 版中移除:?使用?importlib.resources.abc.Traversable?代替。
name
抽象屬性。 此對(duì)象的不帶任何父引用的基本名稱。
abstractmethod?iterdir()
產(chǎn)出?self
?中的?Traversable
?對(duì)象。
abstractmethod?is_dir()
如果?self
?是一個(gè)目錄則返回?True
。
abstractmethod?is_file()
如果?self
?是一個(gè)文件則返回?True
。
abstractmethod?joinpath(child)
返回?self
?中的 Traversable 子對(duì)象。
abstractmethod?__truediv__(child)
返回?self
?中的?Traversable
?子對(duì)象。
abstractmethod?open(mode='r',?*args,?**kwargs)
mode?可以為 'r' 或 'rb' 即以文本或二進(jìn)制模式打開。 返回一個(gè)適用于讀取的句柄(與?pathlib.Path.open?樣同)。
當(dāng)以文本模式打開時(shí),接受與?io.TextIOWrapper?所接受的相同的編碼格式形參。
read_bytes()
以字節(jié)串形式讀取?self
?的內(nèi)容。
read_text(encoding=None)
以文本形式讀取?self
?的內(nèi)容。
class?importlib.abc.TraversableResources
針對(duì)能夠?yàn)?importlib.resources.files()?接口提供服務(wù)的資源讀取器的抽象基類。 子類化?importlib.resources.abc.ResourceReader?并為?importlib.resources.abc.ResourceReader?的抽象方法提供具體實(shí)現(xiàn)。 因此,任何提供了?importlib.abc.TraversableResources?的加載器也會(huì)提供 ResourceReader。
需要支持資源讀取的加載器應(yīng)實(shí)現(xiàn)此接口。
3.9 新版功能.
從 3.12 版起不建議使用,將在 3.14 版中移除:?使用?importlib.resources.abc.TraversableResources?代替。
abstractmethod?files()
為載入的包返回一個(gè)?importlib.resources.abc.Traversable?對(duì)象。
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?配置。未來版本的 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?來查找要搜索的模塊。如果在?sys.path_importer_cache?中沒有找到條目,那會(huì)在?sys.path_hooks?檢索該路徑條目的查找器,找到了則和查到的模塊信息一起存入?sys.path_importer_cache?。如果查找器沒有找到,則緩存中的查找器和模塊信息都存為?None
?,然后返回。
3.4 新版功能.
在 3.5 版更改:?如果當(dāng)前工作目錄不再有效(用空字符串表示),則返回?None
,但在?sys.path_importer_cache?中不會(huì)有緩存值。
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ì)緩存來自文件系統(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)行緩存,通過對(duì)每個(gè)模塊的檢索進(jìn)行狀態(tài)統(tǒng)計(jì),驗(yàn)證緩存是否過期。因?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_spec(fullname,?target=None)
嘗試在?path?中找到處理?fullname?的規(guī)格。
3.4 新版功能.
invalidate_caches()
清理內(nèi)部緩存。
classmethod?path_hook(*loader_details)
一個(gè)類方法,返回供?sys.path_hooks?使用的閉包。 使用直接提供給閉包的路徑參數(shù)和間接提供的?loader_details?閉包將返回一個(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
源文件的路徑
is_package(fullname)
如果?path?看似包的路徑,則返回?True
。
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ì)讓模塊無法應(yīng)用于所有的 Python 版本或字節(jié)碼格式有所改動(dòng)的新版本 Python。
3.3 新版功能.
name
加載器將要處理的模塊名。
path
二進(jìn)制碼文件的路徑。
is_package(fullname)
根據(jù)?path?確定該模塊是否為包。
get_code(fullname)
返回由?path?創(chuàng)建的?name?的代碼對(duì)象。
get_source(fullname)
因?yàn)橛么思虞d器時(shí)字節(jié)碼文件沒有源碼文件,所以返回?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ò)展模塊文件的路徑。
請(qǐng)注意,在默認(rèn)情況下,在子解釋器中導(dǎo)入未實(shí)現(xiàn)多階段初始化的擴(kuò)展模塊 (參見?PEP 489) 將會(huì)失敗,即使在其他情況下能夠成功導(dǎo)入。
3.3 新版功能.
在 3.12 版更改:?在子解釋器中使用時(shí)需要多階段初始化。
name
裝載器支持的模塊名。
path
擴(kuò)展模塊的路徑。
create_module(spec)
根據(jù)?PEP 489?,由給定規(guī)范創(chuàng)建模塊對(duì)象。
3.5 新版功能.
exec_module(module)
根據(jù)?PEP 489,初始化給定的模塊對(duì)象。
3.5 新版功能.
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ò)展模塊沒有源代碼。
get_filename(fullname)
返回?path。
3.4 新版功能.
class?importlib.machinery.NamespaceLoader(name,?path,?path_finder)
一個(gè)針對(duì)命名空間包的?importlib.abc.InspectLoader?具體實(shí)現(xiàn)。 這是一個(gè)私有類的別名,僅為在命名空間包上內(nèi)省?__loader__
?屬性而被設(shè)為公有:
>>>
>>> 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)
針對(duì)特定模塊的導(dǎo)入系統(tǒng)相關(guān)狀態(tài)的規(guī)范說明。 這通常是作為模塊的?__spec__?屬性對(duì)外公開。 在下面的描述中,圓括號(hào)內(nèi)的名稱給出了在模塊對(duì)象上直接可用的對(duì)應(yīng)屬性,例如?module.__spec__.origin?==?module.__file__
。 但是要注意,雖然?values?通常是相等的,但它們也可以因?yàn)閮蓚€(gè)對(duì)象之間沒有進(jìn)行同步而不相等。 舉例來說,有可能在運(yùn)行時(shí)更新模塊的?__file__?而這將不會(huì)自動(dòng)反映在模塊的?__spec__.origin
?中,反之亦然。
3.4 新版功能.
name
(__name__)
模塊的完整限定名稱。?finder?總是應(yīng)當(dāng)將此屬性設(shè)為一個(gè)非空字符串。
loader
(__loader__)
用于加載模塊的?loader。?finder?總是應(yīng)當(dāng)設(shè)置此屬性。
origin
(__file__)
應(yīng)當(dāng)被?loader?用來加載模塊的位置。 例如,對(duì)于從 .py 文件加載的模塊來說這將為文件名。?finder?總是應(yīng)當(dāng)將此屬性設(shè)為一個(gè)有意義的值供?loader?使用。 在少數(shù)沒有可用值的情況下(如命名空間包),它應(yīng)當(dāng)被設(shè)為?None
。
submodule_search_locations
(__path__)
將被用于包的子模塊查找的位置列表。 在大多數(shù)時(shí)候這將為單個(gè)目錄。?finder?應(yīng)當(dāng)將此屬性設(shè)為一個(gè)列表,甚至可以是空列表,以便提示導(dǎo)入系統(tǒng)指定的模塊是一個(gè)包。 對(duì)于非包模塊它應(yīng)當(dāng)被設(shè)為?None
。 對(duì)于命名空間包它會(huì)在稍后被自動(dòng)設(shè)為一個(gè)特殊對(duì)象。
loader_state
finder?可以將此屬性設(shè)為一個(gè)包含額外的模塊專屬數(shù)據(jù)的對(duì)象供加載模塊時(shí)使用。 在其他情況下應(yīng)將其設(shè)為?None
。
cached
(__cached__)
模塊代碼的編譯版本的文件名。?finder?總是應(yīng)當(dāng)設(shè)置此屬性但是對(duì)于不需要存儲(chǔ)已編譯代碼的模塊來說可以將其設(shè)為?None
。
parent
(__package__)
(只讀)指定模塊所在的包的完整限定名稱(或者對(duì)于最高層級(jí)模塊來說則為空字符串)。 如果模塊是包則它將與?name?相同。
has_location
如果 spec 的?origin?指向一個(gè)可加載的位置則為?True
,
在其他情況下為?False
。 該值將確定如何解讀?origin?以及如何填充模塊的?__file__。
importlib.util?—— 導(dǎo)入器的工具程序代碼
源代碼:?Lib/importlib/util.py
本模塊包含了幫助構(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
?來自于當(dāng)前的魔法標(biāo)簽 (參見?get_tag()
; 如果?sys.implementation.cache_tag
?未定義則將會(huì)引發(fā)?NotImplementedError)。
參數(shù)?optimization?用于指定字節(jié)碼文件的優(yōu)化級(jí)別。空字符串代表沒有優(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)的源代碼文件路徑。 舉例來說,如果?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?前面沒有句點(diǎn),那就簡(jiǎn)單地返回?name。這樣就能采用?importlib.util.resolve_name('sys',?__spec__.parent)
?之類的寫法,而無需檢查是否需要?package?參數(shù)。
如果?name?是一個(gè)相對(duì)模塊名稱但?package?為假值(如為?None
?或空字符串)則會(huì)引發(fā)?ImportError。 如果相對(duì)名稱離開了其所在的包(如為從?spam
?包請(qǐng)求?..bacon
?的形式)則也會(huì)引發(fā)?ImportError。
3.3 新版功能.
在 3.9 版更改:?為了改善與 import 語句的一致性,對(duì)于無效的相對(duì)導(dǎo)入嘗試會(huì)引發(fā)?ImportError?而不是?ValueError。
importlib.util.find_spec(name,?package=None)
查找模塊的?spec,可選擇相對(duì)于指定的?package?名稱。 如果該模塊位于?sys.modules?中,則會(huì)返回?sys.modules[name].__spec__
?(除非 spec 為?None
?或未設(shè)置,在此情況下則會(huì)引發(fā)?ValueError)。 在其他情況下將使用?sys.meta_path?進(jìn)行搜索。 如果找不到任何 spec 則返回?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?是在訪問?spec?或設(shè)置模塊屬性時(shí)觸發(fā)的,則不會(huì)觸發(fā) 。
本函數(shù)比?types.ModuleType?創(chuàng)建新模塊要好,因?yàn)橛玫?spec?模塊設(shè)置了盡可能多的導(dǎo)入控制屬性。
3.5 新版功能.
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?的哈希值。基于哈希值的?.pyc
?文件在頭部嵌入了對(duì)應(yīng)源文件內(nèi)容的?source_hash()。
3.7 新版功能.
importlib.util._incompatible_extension_module_restrictions(*,?disable_check)
一個(gè)可以暫時(shí)跳過擴(kuò)展模塊兼容性檢查的上下文管理器。 在默認(rèn)情況下該檢查將被啟用并且當(dāng)在子解釋器中導(dǎo)入單階段初始化模塊時(shí)該檢查會(huì)失敗。 如果多階段初始化模塊沒有顯式地支持針對(duì)子解釋器的 GIL,那么當(dāng)它在一個(gè)有自己的 GIL 的解釋器中被導(dǎo)入時(shí),該檢查也會(huì)失敗。
請(qǐng)注意該函數(shù)是為了適應(yīng)一種不尋常的情況;這種情況可能最終會(huì)消失。 這很有可能不是你需要考慮的事情。
你可以通過實(shí)現(xiàn)多階段初始化的基本接口 (PEP 489) 并假裝支持多解釋器 (或解釋器級(jí)的 GIL) 來獲得與該函數(shù)相同的效果。
警告
使用該函數(shù)來禁用檢查可能會(huì)導(dǎo)致預(yù)期之外的行為甚至崩潰。 它應(yīng)當(dāng)僅在擴(kuò)展模塊開發(fā)過程中使用。
3.12 新版功能.
class?importlib.util.LazyLoader(loader)
此類會(huì)延遲執(zhí)行模塊加載器,直至該模塊有一個(gè)屬性被訪問到。
此類?僅僅?適用于定義?exec_module()?作為需要控制模塊使用何種模塊類型的加載器。 出于相同理由,加載器的?create_module()?方法必須返回?None
?或其?__class__
?屬性可被改變并且不使用?槽位?的類型。 最后,用于替換已放入?sys.modules?的對(duì)象的模塊將無法工作因?yàn)闆]有辦法安全地在整個(gè)解釋器中正確替換模塊引用; 如果檢測(cè)到這種替換則會(huì)引發(fā)?ValueError。
備注
如果項(xiàng)目對(duì)啟動(dòng)時(shí)間要求很高,只要模塊未被用過,此類能夠最小化加載模塊的開銷。對(duì)于啟動(dòng)時(shí)間并不重要的項(xiàng)目來說,由于加載過程中產(chǎn)生的錯(cuò)誤信息會(huì)被暫時(shí)擱置,因此強(qiáng)烈不建議使用此類。
3.5 新版功能.
在 3.6 版更改:?開始調(diào)用?create_module(),移除?importlib.machinery.BuiltinImporter?和?importlib.machinery.ExtensionFileLoader?的兼容性警告。
classmethod?factory(loader)
一個(gè)返回創(chuàng)建延遲加載器的可調(diào)用對(duì)象的類方法。 這專門被用于加載器由類而不是實(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 importlibitertools = importlib.import_module('itertools')
檢查某模塊可否導(dǎo)入。
如果你需要在不實(shí)際執(zhí)行導(dǎo)入的情況下確定某個(gè)模塊是否可被導(dǎo)入,則你應(yīng)當(dāng)使用?importlib.util.find_spec()。
請(qǐng)注意如果?name
?是一個(gè)子模塊(即包含一個(gè)點(diǎn)號(hào)),則?importlib.util.find_spec()?將會(huì)導(dǎo)入父模塊。
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] = modulespec.loader.exec_module(module)print(f"{name!r} has been imported") else:print(f"can't find the {name!r} module")
直接導(dǎo)入源碼文件。
要直接導(dǎo)入 Python 源文件,請(qǐng)使用以下寫法:
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?兩方面。 對(duì)于查找器來說根據(jù)你的需求有兩種類別可供選擇:?meta path finder?或?path entry finder。 前者你應(yīng)當(dāng)放到?sys.meta_path?而后者是使用?path entry hook?在?sys.path_hooks?上創(chuàng)建并與?sys.path?條目一起創(chuàng)建一個(gè)潛在的查找器。 下面的例子將向你演示如何注冊(cè)自己的導(dǎo)入器供導(dǎo)入機(jī)制使用 (關(guān)于自行創(chuàng)建導(dǎo)入器,請(qǐng)閱讀在本包內(nèi)定義的相應(yīng)類的文檔):
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)
導(dǎo)入過程本身是用 Python 代碼實(shí)現(xiàn)的,這樣就有可能通過 importlib 來對(duì)外公開大部分導(dǎo)入機(jī)制。 以下代碼通過提供?importlib.import_module()?的近似實(shí)現(xiàn)來說明 importlib 所公開的幾種 API:
import importlib.util import sysdef 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:passpath = Noneif '.' in absolute_name:parent_name, _, child_name = absolute_name.rpartition('.')parent_module = import_module(parent_name)path = parent_module.__spec__.submodule_search_locationsfor finder in sys.meta_path:spec = finder.find_spec(absolute_name, path)if spec is not None:breakelse: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] = modulespec.loader.exec_module(module)if path is not None:setattr(parent_module, child_name, module)return module