婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Python入門基礎之import機制

Python入門基礎之import機制

熱門標簽:云南地圖標注 電銷機器人 金倫通信 鄭州智能外呼系統中心 北京外呼電銷機器人招商 400電話 申請 條件 賓館能在百度地圖標注嗎 crm電銷機器人 汕頭電商外呼系統供應商 南京crm外呼系統排名

一、前言

本文基于開源項目:

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 sys

In [2]: sys.modules['os'] = None

In [3]: import os
---------------------------------------------------------------------------
ModuleNotFoundError   Traceback (most recent call last)
ipython-input-3-543d7f3a58ae> in module>
----> 1 import os

ModuleNotFoundError: 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 sys

In [2]: sys.meta_path
Out[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 nosuchmodule

ModuleNotFoundError: 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
---------------------------------------------------------------------------
ImportError        Traceback (most recent call last)
ipython-input-6-b7cbf7e60adc> in module>
  11 sys.meta_path = [NoSuchModuleFinder()]
  12 
---> 13 import nosuchmodule

ImportError: 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 module

In [3]: module
Out[3]: module 'module' (__main__.ExampleLoader object at 0x7f7f0d07f890>)>

In [4]: module.x
Out[4]: 1

In [5]: module.y
Out[5]: 2

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

三、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
 ...: module
Out[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 sys

In [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 import .pyd 可能遇到路徑的問題
  • python 指定源路徑來解決import問題的操作
  • 關于Python3的import問題(pycharm可以運行命令行import錯誤)
  • 解決python3.x安裝numpy成功但import出錯的問題
  • python import 上級目錄的導入
  • Python import模塊的緩存問題解決方案

標簽:浙江 梅州 文山 石家莊 懷化 錫林郭勒盟 西寧 昆明

巨人網絡通訊聲明:本文標題《Python入門基礎之import機制》,本文關鍵詞  Python,入門,基礎,之,import,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Python入門基礎之import機制》相關的同類信息!
  • 本頁收集關于Python入門基礎之import機制的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产精品麻豆视频| 成人免费一区二区三区在线观看| 欧美一区中文字幕| 一区二区三区中文在线观看| 成人午夜视频在线| 国产日韩欧美精品电影三级在线| 视频一区二区三区在线| 欧美无砖砖区免费| 亚洲精品videosex极品| 97精品视频在线观看自产线路二| 中文字幕精品三区| 成人黄色a**站在线观看| 日本一区二区在线不卡| 国产美女主播视频一区| 精品999在线播放| 国产成人精品影院| 国产欧美日韩在线看| 国产不卡视频在线播放| 国产精品毛片无遮挡高清| av午夜精品一区二区三区| 亚洲丝袜自拍清纯另类| 欧美性受xxxx| 久久激情五月婷婷| 久久精品人人做人人爽人人| 丰满少妇久久久久久久| 最新国产精品久久精品| 97se亚洲国产综合自在线观| 亚洲一级二级在线| 欧美肥胖老妇做爰| 国产精品18久久久久久久网站| 日本一区二区三区国色天香| 91丨九色丨尤物| 另类欧美日韩国产在线| 成人免费一区二区三区视频| 制服视频三区第一页精品| 国产成人免费av在线| 亚洲一区视频在线| 欧美一区二区性放荡片| 不卡一二三区首页| 国产一区美女在线| 亚洲午夜日本在线观看| 久久综合狠狠综合久久激情| 91久久精品国产91性色tv| 久久se精品一区二区| 亚洲欧美日韩一区二区三区在线观看 | 国产91在线观看| 调教+趴+乳夹+国产+精品| 精品国产乱码久久久久久闺蜜| 99久久婷婷国产| 国产老女人精品毛片久久| 亚洲成a天堂v人片| 国产精品美女久久久久久2018| 欧美成人一级视频| 中文字幕色av一区二区三区| 91啪亚洲精品| 亚洲五码中文字幕| 日韩一区和二区| 成人午夜av影视| 亚洲va欧美va国产va天堂影院| 久久在线观看免费| 国产日韩视频一区二区三区| 极品尤物av久久免费看| 东方欧美亚洲色图在线| 亚欧色一区w666天堂| 国产欧美一区二区精品婷婷| 欧美精品免费视频| 色婷婷久久99综合精品jk白丝| 国产精品一区二区三区四区| 九九在线精品视频| 日韩精品视频网站| 亚洲永久免费av| 亚洲人成7777| 亚洲图片欧美激情| 国产精品色婷婷| 亚洲国产精品成人综合| 国产欧美日韩在线视频| 国产天堂亚洲国产碰碰| 欧美大尺度电影在线| 欧美日韩国产综合视频在线观看| 色爱区综合激月婷婷| 色狠狠色狠狠综合| 色欧美88888久久久久久影院| 99re视频这里只有精品| 91丨九色丨国产丨porny| 99re这里都是精品| 色综合色综合色综合 | 亚洲视频一区在线观看| 亚洲人精品一区| 一区二区在线观看免费| 亚洲电影一级黄| 久久国产精品99久久久久久老狼| 国产在线麻豆精品观看| 高潮精品一区videoshd| 色综合天天视频在线观看| 欧美日韩国产免费| 久久久久久久久久看片| 中文字幕一区二区视频| 亚洲综合视频在线观看| 蜜臀久久久久久久| 国产91精品精华液一区二区三区| 91网站在线播放| 日韩免费在线观看| 1000精品久久久久久久久| 亚洲国产三级在线| 国产精品影视在线观看| 99vv1com这只有精品| 91精品国产综合久久久蜜臀图片 | 精品国产一区二区三区av性色| 欧美日韩午夜在线视频| 久久九九国产精品| 亚洲一卡二卡三卡四卡无卡久久| 狠狠久久亚洲欧美| av综合在线播放| 精品日韩99亚洲| 亚洲一区在线看| 成人一区二区三区| 欧美日韩免费在线视频| 久久精品人人做人人综合| 亚洲一区在线观看视频| 国产一区二区伦理片| 99精品久久只有精品| 日韩一区二区三区视频| 亚洲乱码国产乱码精品精98午夜 | 午夜精品久久久久久不卡8050| 国产裸体歌舞团一区二区| 亚洲成人一区在线| 99久久婷婷国产综合精品电影| 欧美v日韩v国产v| 亚洲成av人影院在线观看网| 成av人片一区二区| 国产欧美日韩在线| 国产剧情一区二区三区| 日韩一区二区视频| 亚洲高清免费观看| 日本乱人伦aⅴ精品| 中文欧美字幕免费| 国产一区二区三区免费在线观看| 欧美性感一类影片在线播放| 亚洲欧洲av色图| 99re这里都是精品| 日韩美女精品在线| gogogo免费视频观看亚洲一| 国产一区二区三区不卡在线观看| 7777精品伊人久久久大香线蕉的| 一区二区三区四区不卡在线| 99国产精品久久久久久久久久久| 精品国产一区二区三区久久久蜜月| 亚洲高清一区二区三区| 欧美三级乱人伦电影| 亚洲午夜电影网| 欧美人与性动xxxx| 日韩av成人高清| 久久网站最新地址| 黑人巨大精品欧美黑白配亚洲| 国产日韩欧美a| 91免费精品国自产拍在线不卡| 一区二区三区在线影院| 欧美日韩高清一区二区| 精品无人码麻豆乱码1区2区 | 亚洲精品久久久久久国产精华液| 91成人在线观看喷潮| 天天亚洲美女在线视频| 26uuu久久天堂性欧美| www.亚洲国产| 五月综合激情婷婷六月色窝| 精品国产乱码久久久久久图片| 国产成人在线视频网址| 一区二区三区视频在线观看| 欧美日韩国产三级| 粉嫩一区二区三区性色av| 亚洲欧美日韩一区二区 | 国产日韩精品一区二区三区| 国产成人在线免费| 亚洲二区在线观看| 久久香蕉国产线看观看99| 欧美日韩亚洲高清一区二区| 亚洲va韩国va欧美va| 91精品欧美久久久久久动漫 | 91麻豆精品在线观看| 日韩精品最新网址| 香港成人在线视频| 色综合色综合色综合色综合色综合| 欧美一区二区在线免费观看| 欧美在线不卡视频| 国产一区二区免费视频| 欧美日韩亚洲丝袜制服| 亚洲美女精品一区| 成人污污视频在线观看| 水野朝阳av一区二区三区| 91极品视觉盛宴| 亚洲欧美电影院| 国产**成人网毛片九色| 91浏览器打开| 国产999精品久久久久久| 精品日韩一区二区| 美美哒免费高清在线观看视频一区二区 | 激情图区综合网| 国产麻豆精品视频| 免费观看在线综合| 日韩欧美亚洲国产另类 |