日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Python入門基礎之import機制

瀏覽:29日期:2022-06-25 15:28:04
一、前言

本文基于開源項目:

github.com/pwwang/pyth…

補充擴展講解,希望能夠讓讀者一文搞懂 Python 的 import 機制。

1.1 什么是 import 機制?

通常來講,在一段 Python 代碼中去執行引用另一個模塊中的代碼,就需要使用 Python 的 import 機制。import 語句是觸發 import 機制最常用的手段,但并不是唯一手段。

importlib.import_module 和 __import__ 函數也可以用來引入其他模塊的代碼。

1.2 import 是如何執行的?

import 語句會執行兩步操作:

搜索需要引入的模塊 將模塊的名字做為變量綁定到局部變量中

搜索步驟實際上是通過 __import__ 函數完成的,而其返回值則會作為變量被綁定到局部變量中。下面我們會詳細聊到 __import__ 函數是如果運作的。

二、import 機制概覽

下圖是 import 機制的概覽圖。不難看出,當 import 機制被觸發時,Python 首先會去 sys.modules 中查找該模塊是否已經被引入過,如果該模塊已經被引入了,就直接調用它,否則再進行下一步。這里 sys.modules 可以看做是一個緩存容器。值得注意的是,如果 sys.modules 中對應的值是 None 那么就會拋出一個 ModuleNotFoundError 異常。下面是一個簡單的實驗:

In [1]: import sysIn [2]: sys.modules[’os’] = NoneIn [3]: import os---------------------------------------------------------------------------ModuleNotFoundError Traceback (most recent call last)<ipython-input-3-543d7f3a58ae> in <module>----> 1 import osModuleNotFoundError: import of os halted; None in sys.modules

如果在 sys.modules 找到了對應的 module,并且這個 import 是由 import 語句觸發的,那么下一步將對把對應的變量綁定到局部變量中。

如果沒有發現任何緩存,那么系統將進行一個全新的 import 過程。在這個過程中 Python 將遍歷 sys.meta_path 來尋找是否有符合條件的元路徑查找器(meta path finder)。sys.meta_path 是一個存放元路徑查找器的列表。它有三個默認的查找器:

內置模塊查找器 凍結模塊(frozen module)查找器 基于路徑的模塊查找器。

In [1]: import sysIn [2]: sys.meta_pathOut[2]: [_frozen_importlib.BuiltinImporter, _frozen_importlib.FrozenImporter, _frozen_importlib_external.PathFinder]

查找器的 find_spec 方法決定了該查找器是否能處理要引入的模塊并返回一個 ModeuleSpec 對象,這個對象包含了用來加載這個模塊的相關信息。如果沒有合適的 ModuleSpec 對象返回,那么系統將查看 sys.meta_path 的下一個元路徑查找器。如果遍歷 sys.meta_path 都沒有找到合適的元路徑查找器,將拋出 ModuleNotFoundError。引入一個不存在的模塊就會發生這種情況,因為 sys.meta_path 中所有的查找器都無法處理這種情況:

In [1]: import nosuchmodule---------------------------------------------------------------------------ModuleNotFoundError Traceback (most recent call last)<ipython-input-1-40c387f4d718> in <module>----> 1 import nosuchmoduleModuleNotFoundError: No module named ’nosuchmodule’

但是,如果這個手動添加一個可以處理這個模塊的查找器,那么它也是可以被引入的:

In [1]: import sys ...: ...: from importlib.abc import MetaPathFinder ...: from importlib.machinery import ModuleSpec ...: ...: class NoSuchModuleFinder(MetaPathFinder): ...: def find_spec(self, fullname, path, target=None): ...: return ModuleSpec(’nosuchmodule’, None) ...: ...: # don’t do this in your script ...: sys.meta_path = [NoSuchModuleFinder()] ...: ...: import nosuchmodule---------------------------------------------------------------------------ImportErrorTraceback (most recent call last)<ipython-input-6-b7cbf7e60adc> in <module> 11 sys.meta_path = [NoSuchModuleFinder()] 12 ---> 13 import nosuchmoduleImportError: missing loader

可以看到,當我們告訴系統如何去 find_spec 的時候,是不會拋出 ModuleNotFound 異常的。但是要成功加載一個模塊,還需要加載器 loader。

加載器是 ModuleSpec 對象的一個屬性,它決定了如何加載和執行一個模塊。如果說 ModuleSpec 對象是“師父領進門”的話,那么加載器就是“修行在個人”了。在加載器中,你完全可以決定如何來加載以及執行一個模塊。這里的決定,不僅僅是加載和執行模塊本身,你甚至可以修改一個模塊:

In [1]: import sys ...: from types import ModuleType ...: from importlib.machinery import ModuleSpec ...: from importlib.abc import MetaPathFinder, Loader ...: ...: class Module(ModuleType): ...: def __init__(self, name): ...: self.x = 1 ...: self.name = name ...: ...: class ExampleLoader(Loader): ...: def create_module(self, spec): ...: return Module(spec.name) ...: ...: def exec_module(self, module): ...: module.y = 2 ...: ...: class ExampleFinder(MetaPathFinder): ...: def find_spec(self, fullname, path, target=None): ...: return ModuleSpec(’module’, ExampleLoader()) ...: ...: sys.meta_path = [ExampleFinder()]In [2]: import moduleIn [3]: moduleOut[3]: <module ’module’ (<__main__.ExampleLoader object at 0x7f7f0d07f890>)>In [4]: module.xOut[4]: 1In [5]: module.yOut[5]: 2

從上面的例子可以看到,一個加載器通常有兩個重要的方法 create_module 和 exec_module 需要實現。如果實現了 exec_module 方法,那么 create_module 則是必須的。如果這個 import 機制是由 import 語句發起的,那么 create_module 方法返回的模塊對象對應的變量將會被綁定到當前的局部變量中。如果一個模塊因此成功被加載了,那么它將被緩存到 sys.modules。如果這個模塊再次被加載,那么 sys.modules 的緩存將會被直接引用。

Python入門基礎之import機制

三、import 勾子(import hooks)

為了簡化,我們在上述的流程圖中,并沒有提到 import 機制的勾子。實際上你可以添加一個勾子來改變 sys.meta_path 或者 sys.path,從而來改變 import 機制的行為。上面的例子中,我們直接修改了 sys.meta_path。實際上,你也可以通過勾子來實現:

In [1]: import sys ...: from types import ModuleType ...: from importlib.machinery import ModuleSpec ...: from importlib.abc import MetaPathFinder, Loader ...: ...: class Module(ModuleType): ...: def __init__(self, name): ...: self.x = 1 ...: self.name = name ...: ...: class ExampleLoader(Loader): ...: def create_module(self, spec): ...: return Module(spec.name) ...: ...: def exec_module(self, module): ...: module.y = 2 ...: ...: class ExampleFinder(MetaPathFinder): ...: def find_spec(self, fullname, path, target=None): ...: return ModuleSpec(’module’, ExampleLoader()) ...: ...: def example_hook(path): ...: # some conditions here ...: return ExampleFinder() ...: ...: sys.path_hooks = [example_hook] ...: # force to use the hook ...: sys.path_importer_cache.clear() ...: ...: import module ...: moduleOut[1]: <module ’module’ (<__main__.ExampleLoader object at 0x7fdb08f74b90>)>四、元路徑查找器(meta path finder)

元路徑查找器的工作就是看是否能找到模塊。這些查找器存放在 sys.meta_path 中以供 Python 遍歷(當然它們也可以通過 import 勾子返回,參見上面的例子)。每個查找器必須實現 find_spec 方法。如果一個查找器知道怎么處理將引入的模塊,find_spec 將返回一個 ModuleSpec 對象(參見下節)否則返回 None。和之前提到的一樣 sys.meta_path 包含三種查找器:

內置模塊查找器 凍結模塊查找器 基于路徑的查找器

這里我們想重點聊一聊基于路徑的查找器(path based finder)。它用于搜索一系列 import 路徑,每個路徑都用來查找是否有對應的模塊可以加載。默認的路徑查找器實現了所有在文件系統的特殊文件中查找模塊的功能,這些特殊文件包括 Python 源文件(.py 文件),Python 編譯后代碼文件(.pyc 文件),共享庫文件(.so 文件)。如果 Python 標準庫中包含 zipimport,那么相關的文件也可用來查找可引入的模塊。

路徑查找器不僅限于文件系統中的文件,它還可以上 URL 數據庫的查詢,或者其他任何可以用字符串表示的地址。

你可以用上節提供的勾子來實現對同類型地址的模塊查找。例如,如果你想通過 URL 來 import 模塊,那么你可以寫一個 import 勾子來解析這個 URL 并且返回一個路徑查找器。

注意,路徑查找器不同于元路徑查找器。后者在 sys.meta_path 中用于被 Python 遍歷,而前者特指基于路徑的查找器。

五、ModuleSpec 對象

每個元路徑查找器必須實現 find_spec 方法,如果該查找器知道如果處理要引入的模塊,那么這個方法將返回一個 ModuleSpec 對象。這個對象有兩個屬性值得一提,一個是模塊的名字,而另一個則是查找器。如果一個 ModuleSpec 對象的查找器是 None,那么類似 ImportError: missing loader 的異常將會被拋出。查找器將用來創建和執行一個模塊(見下節)。

你可以通過 <module>.__spec__ 來查找模塊的 ModuleSpec 對象:

In [1]: import sysIn [2]: sys.__spec__Out[2]: ModuleSpec(name=’sys’, loader=<class ’_frozen_importlib.BuiltinImporter’>)六、加載器(loader)

加載器通過 create_module 來創建模塊以及 exec_module 來執行模塊。通常如果一個模塊是一個 Python 模塊(非內置模塊或者動態擴展),那么該模塊的代碼需要在模塊的 __dict__ 空間上執行。如果模塊的代碼無法執行,那么就會拋出 ImportError 異常,或者其他在執行過程中的異常也會被拋出。

絕大多數情況下,查找器和加載器是同一個東西。這種情況下,查找器的 find_spec 方法返回的 ModuleSpec 對象的 loader 屬性將指向它自己。

我們可以用 create_module 來動態創建一個模塊,如果它返回 None Python 會自動創建一個模塊。

七、總結

Python 的 import 機制靈活而強大。以上的介紹大部分是基于官方文檔,以及較新的 Python 3.6+ 版本。由于篇幅,還有很多細節并沒有包含其中,例如子模塊的加載、模塊代碼的緩存機制等等。文章中也難免出現紕漏如果有任何問題,歡迎到 github.com/pwwang/pyth… 開 issue 提問及討論。

到此這篇關于Python入門基礎之import機制的文章就介紹到這了,更多相關Python import機制內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Python 編程
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲综合中文| 国产v综合v| 久久uomeier| 91久久久精品国产| 久久亚洲风情| 香蕉精品久久| 亚洲一区亚洲| 91九色综合| 欧美激情福利| 日韩国产网站| 免费在线观看日韩欧美| 欧美一级网址| 精品亚洲美女网站| 亚洲精品在线a| 精品美女久久| a国产在线视频| 日韩黄色av| 亚洲成人一区在线观看| 亚洲a级精品| 少妇久久久久| 久久亚洲风情| 日韩精品永久网址| 日韩高清电影免费| 99国产精品免费视频观看| 久久国产日韩欧美精品| 欧美高清不卡| 蜜桃成人av| 亚洲欧洲美洲国产香蕉| 日韩精品1区| 国产日本亚洲| 日韩一区二区三区免费播放| 天堂成人国产精品一区| 国产福利电影在线播放| 蜜臀av性久久久久蜜臀aⅴ流畅 | 成人精品天堂一区二区三区| 欧美自拍一区| 欧美粗暴jizz性欧美20| 国产日韩欧美一区二区三区在线观看| 一区三区视频| 国产精品宾馆| 亚洲伊人影院| 黄毛片在线观看| 日本少妇精品亚洲第一区| 精品日产乱码久久久久久仙踪林| 日韩中文字幕无砖| 国产精品毛片在线看| 日韩精品一级二级| 欧美日韩18| 中文字幕一区二区av| 欧美二区视频| 另类小说一区二区三区| 日韩av影院| 亚洲精品国产日韩| 五月精品视频| 亚洲天堂1区| 午夜精品影视国产一区在线麻豆| 少妇精品导航| 国产不卡av一区二区| 欧美一区=区| 欧美日韩精品免费观看视频完整| av高清不卡| 日韩av自拍| 丰满少妇一区| 在线人成日本视频| 日韩视频1区| 亚洲精一区二区三区| 国产精品88久久久久久| 国产精品亚洲一区二区三区在线观看| 麻豆视频一区二区| 国产高清亚洲| 日韩avvvv在线播放| 国产毛片久久久| 日日夜夜免费精品视频| 欧美日韩国产免费观看视频| 香蕉久久精品| 亚洲国产专区| 欧美日韩水蜜桃| 欧美激情五月| av资源亚洲| 欧美日韩国产高清| 久久www成人_看片免费不卡| 亚洲在线网站| 亚洲三级av| 国产精品s色| 国语对白精品一区二区| 毛片不卡一区二区| 在线手机中文字幕| 欧美另类中文字幕| 综合亚洲色图| 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲免费播放| 欧美国产91| 丝袜亚洲另类欧美| 日韩国产欧美在线视频| 国产欧美啪啪| 国产a亚洲精品| 日韩一区二区三区在线免费观看| 国产精品毛片一区二区三区| 久久精品导航| 蜜桃精品在线| 精品在线网站观看| 蜜臀久久99精品久久一区二区| 久久99高清| 国产一区二区三区探花| 欧美在线日韩| 人人爱人人干婷婷丁香亚洲| 日韩精品免费视频一区二区三区| 99久久亚洲精品蜜臀| 久久久久一区| 亚洲涩涩在线| 日韩欧美网址| 久久亚洲精品中文字幕蜜潮电影| 国产成人a视频高清在线观看| 久久在线91| 国产日韩电影| 日本综合字幕| 久久在线免费| 日韩在线二区| 久久精品亚洲人成影院| 亚洲免费播放| 亚洲作爱视频| 亚洲色图网站| 亚洲一区二区三区无吗| 中文字幕中文字幕精品| 亚洲免费专区| 国产欧美日韩精品一区二区免费| 六月丁香综合在线视频| 国产精品一区二区美女视频免费看| 中文字幕成人| 国产日韩高清一区二区三区在线 | 亚洲精品一二三区区别| 久久一区二区三区电影| 久久一二三区| 亚洲成人精品| 国产综合视频| 噜噜噜久久亚洲精品国产品小说| 久久国产88| 欧美日韩18| 国产精品久av福利在线观看| 国产精品久久久久久久久久久久久久久| 久久麻豆视频| 精品国产一级| 欧美不卡在线| 亚洲欧美日韩国产| 伊人精品在线| 国产精品密蕾丝视频下载| 精品无人区麻豆乱码久久久| 激情中国色综合| 精品精品久久| 日韩国产综合| 伊人久久亚洲热| 亚洲精选91| 成人精品国产亚洲| 热三久草你在线| 9色国产精品| 日本在线一区二区三区| 日韩影院二区| 黄色不卡一区| 国产精品一级| 日本午夜精品一区二区三区电影| 人人精品久久| 国产精品亚洲欧美| 久久视频精品| 国产精品中文| 婷婷成人在线| 国产精品美女久久久久久不卡| 四虎国产精品免费观看| 91久久久久| 欧美www视频在线观看| 丝袜亚洲精品中文字幕一区| 精品国产黄a∨片高清在线| 国产欧美日韩精品一区二区免费 | 丝袜美腿一区| 中文字幕av一区二区三区人| 热久久久久久| 精品国内亚洲2022精品成人| 国产在线日韩精品| 99在线精品视频在线观看| 免费成人性网站| 日精品一区二区三区| 久久gogo国模啪啪裸体| 精品1区2区3区4区| 精品九九久久| 欧美精选一区二区三区| 毛片不卡一区二区| 日韩国产欧美| 久久精品72免费观看| 丝袜诱惑制服诱惑色一区在线观看 | 亚洲精品在线观看91| 国产精品亚洲欧美| 精品亚洲二区| 国产黄色一区| 日韩视频久久| 色在线视频观看| 国产66精品| 欧美国产中文高清| 欧美日韩午夜电影网| 亚洲一区免费| 日韩视频免费| 欧美99久久|