Python将importlib作为标准库提供。它旨在提供Pythonimport语法和(__import__()函数)的实现。另外,importlib提供了开发者可以创建自己的对象(即importer)来处理导入过程。

那么imp呢?还有一个imp模块提供了import语句接口,不过这个模块在Python3.4已经deprecated了。建议使用importlib来处理。

这个模块比较复杂,文中我们主要探讨如下主题:

  • 动态导入
  • 检查模块是否可以导入
  • 从源文件导入

我们先从动态导入开始。

动态导入

importlib模块支持传递字符串来导入模块。我们先来创建一些简单模块一遍演示。我们在模块里提供了相同接口,通过打印它们自身名字来区分。我们分别创建了foo.pybar.py,代码如下:

def main():
print(__name__)

现在我们尽需要使用importlib导入它们。我们来看看代码是如何实现的,确保该代码在刚才创建的两个文件的相同目录下。

#importer
import importlib def dynamic_import(module):
return importlib.import_module(module) if __name__ == "__main__":
module = dynamic_import('foo')
module.main() module2 = dynamic_import('bar')
module2.main()

这里我们导入importlib模块,并创建了一个非常简单的函数dynamic_import。这个函数直接就调用了importlib的import_module方法,并将要导入的模块字符串传递作为参数,最后返回其结果。然后在主入口中我们分别调用了各自的main方法,将打印出各自的name.

$ python3 importer.py
foo
bar

也许你很少会代码这么做,不过在你需要试用字符串作为导入路径的话,那么importlib就有用途了。

模块导入检查

Python有个众所周知的代码风格EAFP: Easier to ask forgiveness than permission.它所代表的意思就是总是先确保事物存在(例如字典中的键)以及在犯错时捕获。如果我们在导入前想检查是否这个模块存在而不是靠猜。 使用mportlib就能实现。

import importlib.util

def check_module(module_name):
"""
Checks if module can be imported without actually
importing it
"""
module_spec = importlib.util.find_spec(module_name)
if module_spec is None:
print("Module: {} not found".format(module_name))
return None
else:
print("Module: {} can be imported".format(module_name))
return module_spec def import_module_from_spec(module_spec):
"""
Import the module via the passed in module specification
Returns the newly imported module
"""
module = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
return module if __name__ == '__main__':
module_spec = check_module('fake_module')
module_spec = check_module('collections')
if module_spec:
module = import_module_from_spec(module_spec)
print(dir(module))

这里我导入了importlib的子模块util。check_module里面调用find_spec方法, 传递该模块字符串作为参数。当我们分别传入了一个不存在和存在的Python模块。你可以看到当你传入不存在的模块时,find_spec函数将返回 None,在我们代码里就会打印提示。如果存在我们将返回模块的specification。

我们可以通过该模块的specification来实际导入该模块。或者你直接将字符串作为参数调用import_module函数。不过我这里也学习如何试用模块specification方式导入。看看import_module_from_spec函数。它接受check_module提供的模块specification作为参数。然后我们将它传递给了module_from_spec函数,它将返回导入模块。Python文档推荐导入后然后执行模块,所以接下来我们试用exec_module函数执行。最后我们使用dir来确保得到预期模块。

从源代码导入

importlib的子模块有个很好用的技巧我想提提。你可以使用util通过模块的名字和路径来导入模块。

import importlib.util

def import_source(module_name):
module_file_path = module_name.__file__
module_name = module_name.__name__ module_spec = importlib.util.spec_from_file_location(
module_name, module_file_path
)
module = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
print(dir((module))) msg = 'The {module_name} module has the following methods {methods}'
print(msg.format(module_name=module_name, methods=dir(module))) if __name__ == "__main__":
import logging
import_source(logging)

在上面的代码中,我们实际导入logging模块,并将模块传递给了import_source函数。这样我们就可以通过导入的模块获取到实际的路 径和名字。然后我们将信息传递给sec_from_file_location函数,它将返回模块的specification。也了这个我们就可以在前 面那样直接通过importlib导入了。

总结

目前,你知道如何在代码中使用importlib和import钩子。这个模块内容非常多,如果你想自定义importer或者loader,那么你可以通过官方文档或者源代码了解更多。

最新文章

  1. html基础 样式
  2. nginx Windows服务形式运行
  3. iOS 最全面试题
  4. 预定义宏_GNUC_ _MSC_VER
  5. SQLSERVER2000使用TSQL将数据导入ACCESS并压缩生成rar
  6. Android开发之PagerAdapter
  7. MySQL安装配置,命令,异常纪要
  8. JavaSE_ API常用对象 总目录(11~14)
  9. P3414 SAC#1 - 组合数 题解
  10. 零拷贝sendfile解析
  11. 如何在服务器上搭建svn
  12. vue中使用localStorage存储信息
  13. 不同意义的new和delete
  14. [oracle] 两种权限:系统权限VS对象权限
  15. 获取web.xml配置文件中的初始化值
  16. 封装baseControl
  17. 记录code修改
  18. 内存中加载DLL DELPHI版
  19. Leetcode:Merge k Sorted Lists分析和实现
  20. ASP.NET Web网站中App_Code文件夹的作用及使用场景

热门文章

  1. hdu1003 最大子串和
  2. Extjs,实现树形结构的总结
  3. PHP——0126最初
  4. IE9 BUG overflow :auto 底部空白解决方案
  5. ES6学习笔记(1,let和const)
  6. KMP + 求最小循环节 --- HUST 1010 - The Minimum Length
  7. Thymeleaf 3.0.9.RELEASE is the current stable version. It requires Java SE 6 or newer.
  8. 在XML中用于注释的符号是。(选择1项)
  9. powershell---高级函数的介绍
  10. uilabel 和uitextview 自适应大小