16.6. 动态导入模块

好了,关于哲学的讨论就到此为止。让我们来谈谈如何动态导入模块。

首先,让我们看看通常如何导入模块。import module 语法会在搜索路径中查找指定的模块,并按名称导入它。您甚至可以使用这种方法一次导入多个模块,只需用逗号分隔列表即可。您在本章脚本的第一行就做到了这一点。

示例 16.13. 一次导入多个模块


import sys, os, re, unittest 1
1 这会一次导入四个模块:sys(用于系统函数和访问命令行参数)、os(用于操作系统函数,如目录列表)、re(用于正则表达式)和 unittest(用于单元测试)。

现在让我们做同样的事情,但使用动态导入。

示例 16.14. 动态导入模块

>>> sys = __import__('sys')           1
>>> os = __import__('os')
>>> re = __import__('re')
>>> unittest = __import__('unittest')
>>> sys                               2
>>> <module 'sys' (built-in)>
>>> os
>>> <module 'os' from '/usr/local/lib/python2.2/os.pyc'>
1 内置的 __import__ 函数实现了与使用 import 语句相同的目标,但它是一个实际的函数,并且它接受一个字符串作为参数。
2 变量 sys 现在是 sys 模块,就像您说过 import sys 一样。变量 os 现在是 os 模块,依此类推。

所以 __import__ 导入一个模块,但需要一个字符串参数来完成。在本例中,您导入的模块只是一个硬编码的字符串,但它也可以是一个变量,或者是一个函数调用的结果。而且,您为其分配模块的变量也不必与模块名称匹配。您可以导入一系列模块并将它们分配给一个列表。

示例 16.15. 动态导入模块列表

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 1
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)        2
>>> modules                                       3
[<module 'sys' (built-in)>,
<module 'os' from 'c:\Python22\lib\os.pyc'>,
<module 're' from 'c:\Python22\lib\re.pyc'>,
<module 'unittest' from 'c:\Python22\lib\unittest.pyc'>]
>>> modules[0].version                            4
'2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)]'
>>> import sys
>>> sys.version
'2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)]'
1 moduleNames 只是一个字符串列表。没什么特别的,只是这些字符串恰好是您可以导入的模块的名称,如果您想这样做的话。
2 令人惊讶的是,您想导入它们,并且您确实这样做了,方法是将 __import__ 函数映射到列表上。请记住,这会获取列表的每个元素(moduleNames)并反复调用函数(__import__),每次使用列表中的一个元素,构建返回值列表,并返回结果。
3 所以现在,您已经从一个字符串列表创建了一个实际模块列表。(您的路径可能会有所不同,具体取决于您的操作系统、Python 安装位置、月相等等。)
4 为了说明这些是真正的模块,让我们看看一些模块属性。请记住,modules[0] sys 模块,所以 modules[0].version sys.version。这些模块的所有其他属性和方法也可用。 import 语句没有什么神奇之处,模块也没有什么神奇之处。模块是对象。一切都是对象。

现在,您应该能够将所有这些内容结合起来,并弄清楚本章代码示例的大部分内容在做什么。