参考链接:

An approach to lazy importing in Python 3.7(这个是参考源)

Python3.7中一种懒加载的方式(中文翻译)

原博客核心:

以前的两种惰性/延迟加载方法:

  ①本地子功能区加载而非程序启动时的全局加载。直到你的程序运行需要这个库的时候才进行加载;缺点:易重复载入库文件、容易遗忘库载入的范围。

  ②惰性加载。需要模块的时候触发 ModuleNotFoundError  提前发现这个模块,而延迟的只是后续补加载过程;缺点:显式优于隐式、如果一个模块希望立即加载,那么在延迟加载时,它可能会严重崩溃。(Mercurial实际上开发了一个模块黑名单,以避免延迟加载来解决这个问题,但是他们必须确保对其进行更新,因此这也不是一个完美的解决方案。)

博主提出来的最新的方法:

  在Python 3.7中,模块现在可以在其上定义__getattr__(),允许编写一个函数,在模块上的属性不可用时导入模块。这样做的缺点是使它成为一个惰性导入而不是一个加载,因此很晚才发现是否会引发ModuleNotFoundError。但是它是显式的,并且仍然是为您的模块全局定义的,因此更容易控制。

改进方向:发现导入错误被推迟,如何提前获知这个可能出现的导入错误防止程序抛出异常并终止。

代码段1:demo1.py

 import importlib

 # 这个是实现lazy_import的功能函数
def lazy_import(importer_name, to_import):
module = importlib.import_module(importer_name) # 直接加载调用的后一级函数 import_mapping = {} # 字典 键名:有可能为缩写名 值名:为原始可查找库名,例如:import_mapping['np'] = 'numpy'
for name in to_import:
importing, _, binding = name.partition(' as ')
if not binding:
_, _, binding = importing.rpartition('.')
import_mapping[binding] = importing def __getattr__(name):
if name not in import_mapping: # 如果这个库没在import_mapping中,就抛出异常错误,并且中断
message = f'module {importer_name!r} has no attribute {name!r}'
raise AttributeError(message)
importing = import_mapping[name]
imported = importlib.import_module(importing,module.__spec__.parent)
# print('name=',name,'module=',module,'module.__spec__=',module.__spec__,'module.__spec__.parent=',module.__spec__.parent)
setattr(module, name, imported) # sub, np, numpy
return imported return module, __getattr__ #返回一个库和一个方法

代码段2:sub.py

lazy_import 在python3.7中已经可以直接使用了
 # In pkg/__init__.py with a pkg/sub.py.
import demo1 # print('sub.py中的__name__ =', __name__)  #当其他程序调用这个程序的时候 __name__ = 'sub',自己为主程序的时候为 '__main__',这里我第一次使用的时候就出错了,直接在这个程序中测试
mod, __getattr__ = demo1.lazy_import(__name__, {'sys', '.sub as thingy', 'numpy as np'}) def test1():
print('sys运行正常')
return mod.sys def test2():
return mod.thingy.answer def test3():
print('numpy运行正常')
return mod.np

代码段3:mid_test.py

 import sub

 ### 异常检测,str_out是不存在的,抛出异常处理
# module1 = sub.str_out() module2 = sub.test3()
print(module2)
# <module 'numpy' from 'C:\\ProgramData\\Anaconda3\\envs\\lib\\site-packages\\numpy\\__init__.py'> print(module2.array([1, 2, 3, 4]))
# [1 2 3 4] print(module2.__spec__)
# ModuleSpec(
# name='numpy',
# loader=<_frozen_importlib_external.SourceFileLoader object at 0x000001E4879A6F98>,
# origin='C:\\ProgramData\\Anaconda3\\envs\\lib\\site-packages\\numpy\\__init__.py',
# submodule_search_locations=['C:\\ProgramData\\Anaconda3\\envs\\lib\\site-packages\\numpy']) print(module2.__spec__.parent)
# numpy

lazy_import源码解析(原创)的更多相关文章

  1. [原创]android开源项目源码解析(一)----CircleImageView的源码解析

    CircleImageView的代码很简洁,因此先将此工程作为源码解析系列的第一篇文章. 解析说明都在代码里了. /* * Copyright 2014 - 2015 Henning Dodenhof ...

  2. 【原创】backbone1.1.0源码解析之View

    作为MVC框架,M(odel)  V(iew)  C(ontroler)之间的联系是必不可少的,今天要说的就是View(视图) 通常我们在写逻辑代码也好或者是在ui组件也好,都需要跟dom打交道,我们 ...

  3. 【原创】backbone1.1.0源码解析之Collection

    晚上躺在床上,继续完成对Backbone.Collection的源码解析. 首先讲讲它用来干嘛? Backbone.Collection的实例表示一个集合,是很多model组成的,如果用model比喻 ...

  4. HashMap源码解析 非原创

    Stack过时的类,使用Deque重新实现. HashCode和equals的关系 HashCode为hash码,用于散列数组中的存储时HashMap进行散列映射. equals方法适用于比较两个对象 ...

  5. Spring-cloud & Netflix 源码解析:Eureka 服务注册发现接口 ****

    http://www.idouba.net/spring-cloud-source-eureka-client-api/?utm_source=tuicool&utm_medium=refer ...

  6. jQuery整体架构源码解析(转载)

    jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...

  7. solr&lucene3.6.0源码解析(四)

    本文要描述的是solr的查询插件,该查询插件目的用于生成Lucene的查询Query,类似于查询条件表达式,与solr查询插件相关UML类图如下: 如果我们强行将上面的类图纳入某种设计模式语言的话,本 ...

  8. solr&lucene3.6.0源码解析(三)

    solr索引操作(包括新增 更新 删除 提交 合并等)相关UML图如下 从上面的类图我们可以发现,其中体现了工厂方法模式及责任链模式的运用 UpdateRequestProcessor相当于责任链模式 ...

  9. android源码解析(十七)-->Activity布局加载流程

    版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...

随机推荐

  1. 安卓学习第一节--环境搭建及Android Studio 安装

    1.安装JDK 2.安装AS 安装参考网址 https://www.cnblogs.com/xiadewang/p/7820377.html 下载网址: http://www.android-stud ...

  2. Listener随笔

    [1]监听器简介   > Listener是JavaWeb中三大组件之一.Servlet.Filter.Listener   > 三大组件都有的共同特点,都需要实现一个接口,并在web.x ...

  3. ftp协议 主动和被动两种模式模式

  4. 压力测试工具 Apache_jmeter软件配置+TCP示例说明

    该软件jmeter是Apache官方开源压力测试软件.  jmeter官网:http://jmeter.apache.org/  . 本文使用的版本是 3.0版本, 它需要jdk7及以上版本支持. 网 ...

  5. 利用AnyProxy代理监控APP流量

    1.介绍 AnyProxy 是阿里巴巴基于 Node.js 开发的一款开源代理服务器. 代理服务器站在客户端和服务端的中间,它可以收集双方通信的每个比特.一个完整的代理请求过程为:客户端首先与代理服务 ...

  6. http中post和get方法区别

  7. Lambda表达式遍历和泛型ForEach遍历方式

    lambda表态式 DataTable dtAllItems = policySecurity.GetUserAccessTypeOnAllItems(userID); List<DataRow ...

  8. php实现最简单的MVC框架实例教程

    本文以一个实例的形式讲述了PHP实现MVC框架的过程,比较浅显易懂.现分享给大家供大家参考之用.具体分析如下: 首先,在学习一个框架之前,基本上我们都需要知道什么是mvc,即model-view-co ...

  9. 汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等

    转自:http://www.51testing.com/html/83/n-3718883.html 有人认为编程是一门技术活,要有一定的天赋,非天资聪慧者不能及也.非也,这是近几年,对于技术这碗饭有 ...

  10. java面试一、1.2集合

    免责声明:     本文内容多来自网络文章,转载为个人收藏,分享知识,如有侵权,请联系博主进行删除. 1.2常见集合 List.Set.Map的区别以及选用 List和Set都继承与Collectio ...