1. Importer协议

协议涉及两个对象: Finder 和 loader

1. Finder

实现了方法:

finder.find_module(fullname, path=None)

返回一个loader对象或者None。

2. Loader

实现了方法:

loader.load_module(fullname)

返回一个module对象或者raise an exception

参考:pep302

2. 注册hooks

hooks有两种,一种是Meta hooks,一种是Path hooks。

注册方式:

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))

参考:

pep302

importlib

3. 流程

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] # 先查询sys.modules
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: # 再从sys.meta_path中获取finder
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

其中:

sys.meta_path[-1]类型是<class '_frozen_importlib_external.PathFinder'>, 这个对象调用了sys.path以及sys.path_hooks。

注意:

本来按照pep302的导入逻辑,是:

for mp in sys.meta_path:
loader = mp(fullname)
if loader is not None:
<module> = loader.load_module(fullname) for path in sys.path:
for hook in sys.path_hooks:
try:
importer = hook(path)
except ImportError:
# ImportError, so try the other path hooks
pass
else:
loader = importer.find_module(fullname)
<module> = loader.load_module(fullname) # Not found!
raise ImportError

但后来(python3.4)引入了pep451, 接口名和调用方式发生了一些变化,使得流程如3所示。

主要参考:

pep302

pep451

importlib

New Import Hooks

Python 类库引入机制

学习python importlib的导入机制的更多相关文章

  1. Python importlib(动态导入模块)

    使用 Python importlib(动态导入模块) 可以将字符串型的模块名导入 示例: import importlib module = 'module name' # 字符串型模块名 test ...

  2. python importlib动态导入模块

    一般而言,当我们需要某些功能的模块时(无论是内置模块或自定义功能的模块),可以通过import module 或者 from * import module的方式导入,这属于静态导入,很容易理解. 而 ...

  3. python的模块导入机制

    在python中用import或者from...import来导入相应的模块. 模块(Module)其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模 ...

  4. 学习python最难的就是入门,而这文章刚好适合初学者!

    Python可以应用于众多领域,如:数据分析.组件集成.网络服务.图像处理.数值计算和科学计算等众多领域.目前业内几乎所有大中型互联网企业都在使用Python,如:Youtube.Dropbox.BT ...

  5. Python 实现自动导入缺失的库

    原文:由浅入深:Python 中如何实现自动导入缺失的库? 作者:豌豆花下猫 在写 Python 项目的时候,我们可能经常会遇到导入模块失败的错误:ImportError: No module nam ...

  6. 国内某Python大神自创完整版,系统性学习Python

    很多小伙伴纠结于这个一百天的时间,我觉得完全没有必要,也违背了我最初放这个大纲上来的初衷,我是觉得这个学习大纲还不错,自学按照这个来也能相对系统的学习知识,而不是零散细碎的知识最后无法整合,每个人的基 ...

  7. Python学习--Python基础语法

    第一个Python程序 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码. linux上你只需要在命令行中输入 Python 命令即可启动交互式编程,提示窗 ...

  8. 学习Python的三种境界

    前言 王国维在<人间词话>中将读书分为了三种境界:"古今之成大事业.大学问者,必经过三种之境界:'昨夜西风凋碧树,独上高楼,望尽天涯路'.此第一境也.'衣带渐宽终不悔,为伊消得人 ...

  9. 编程零基础应当如何开始学习 Python?

    提前说一下,这篇福利多多,别的不说,直接让你玩回最有手感的怀旧游戏,参数贴图很方便自己可以根据喜好修改哦. 本篇通过以下四块展开,提供大量资源对应. 选一个好版本 有没有看过<在下坂本,有何贵干 ...

随机推荐

  1. 关联tomcat源代码

    1.进入tomcat官网下载对应版本源代码文件 2. 3..ctrl+鼠标左键 点击Cookie对象 4. 5.

  2. 深入理解Java虚拟机读书笔记8----Java内存模型与线程

    八 Java内存模型与线程   1 Java内存模型     ---主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.     ---此处的变量和J ...

  3. tcp那个孤独的小包到底怎么回事?

    内核3.10,接<tcp的发送端一个小包就能打破对端的delay_ack么?> 我们继续来分析这个没满mss的小包, 可以看到,由于受到syn ack这端是发包端,所以该发送链路协商的ms ...

  4. 爬虫之进阶 twisted

    简介 Twisted是用Python实现的基于事件驱动的网络引擎框架.Twisted诞生于2000年初,在当时的网络游戏开发者看来,无论他们使用哪种语言,手中都鲜有可兼顾扩展性及跨平台的网络库.Twi ...

  5. Linux NGINX部署

    一.Nginx简介 Nginx是一个web服务器也可以用来做负载均衡及反向代理使用,目前使用最多的就是负载均衡,具体简介我就不介绍了百度一下有很多,下面直接进入安装步骤 二.Nginx安装 1.下载N ...

  6. Django SCRF跨站点请求伪造

    使用Django发POSTt请求的时候经常会遇到Forbidden的错误,然后直接了当的方法就是去setting里面吧csrf中间件注释掉,其实csrf是django给我们提供的防护措施. CSRF就 ...

  7. json,json对象以及js对象字面量的区别

    从定义看: json:一种数据交换格式 json对象:js的一个内置对象,拥有JSON.stringify()和JSON.parse()两个方法 js对象字面量:封闭在花括号对({})中的一个对象的零 ...

  8. API权限设计总结

    最近在做API的权限设计这一块,做一次权限设计的总结. 1. 假设我们需要访问的API接口是这样的:http://xxxx.com/openapi/v1/get/user/?key=xxxxx& ...

  9. 云笔记项目-Spring事务学习-传播NOT_SUPPORTED

    接下来测试事务传播属性设置为NOT_SUPPORTED Service层 Service层主要设置如下,其中还插入了REQUIRED作为比较. package Service; import java ...

  10. 云笔记项目-Spring事务学习-传播SUPPORTS

    接下来测试事务传播属性SUPPORTS Service层 Service层将方法的事务传播属性设置为SUPPORTS LayerT层代码 package LayerT; import javax.an ...