6.4. 使用 `sys
.modules`
与其它任何 Python 的东西一样,模块也是对象。只要导入了,总可以用全局 dictionary `sys
.modules` 来得到一个模块的引用。
例 6.12. `sys
.modules` 介绍
>>> import sys
>>> print '\n'.join(sys.modules.keys())
win32api
os.path
os
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
[1] | sys 模块包含了系统级的信息,像正在运行的 Python 的版本 (sys`.version` 或 sys.version_info ),和系统级选项,像最大允许递归的深度 (sys`.getrecursionlimit()` 和 sys.setrecursionlimit() )。 |
[2] | sys`.modules` 是一个字典,它包含了从 Python 开始运行起,被导入的所有模块。键字就是模块名,键值就是模块对象。请注意除了你的程序导入的模块外还有其它模块。Python 在启动时预先装入了一些模块,如果你在一个 Python IDE 环境下, sys.modules 包含了你在 IDE 中运行的所有程序所导入的所有模块。 |
下面的例子展示了如何使用 `sys
.modules`。
例 6.13. 使用 `sys
.modules`
>>> import fileinfo
>>> print '\n'.join(sys.modules.keys())
win32api
os.path
os
fileinfo
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
>>> fileinfo
<module 'fileinfo' from 'fileinfo.pyc'>
>>> sys.modules["fileinfo"]
<module 'fileinfo' from 'fileinfo.pyc'>
[1] | 当导入新的模块,它们加入到 sys`.modules` 中。这就解释了为什么第二次导入相同的模块时非常的快:Python 已经在 sys.modules 中装入和缓冲了,所以第二次导入仅仅对字典做了一个查询。 |
[2] | 一旦给出任何以前导入过的模块名 (以字符串方式),通过 `sys .modules` 字典,你可以得到对模块本身的一个引用。 |
下面的例子将展示通过结合使用 __module__
类属性和 `sys
.modules` dictionary 来获取已知类所在的模块。
例 6.14. __module__
类属性
>>> from fileinfo import MP3FileInfo
>>> MP3FileInfo.__module__
'fileinfo'
>>> sys.modules[MP3FileInfo.__module__]
<module 'fileinfo' from 'fileinfo.pyc'>
[1] | 每个 Python 类都拥有一个内置的类属性 __module__ ,它定义了这个类的模块的名字。 |
[2] | 将它与 `sys .modules` 字典复合使用,你可以得到定义了某个类的模块的引用。 |
现在准备好了,看看在样例程序 第 5 章 `sys
.modules介绍的
fileinfo.py` 中是如何使用的。这个例子显示它的一部分代码。
例 6.15. fileinfo.py
中的 `sys
.modules`
def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
"get file info class from filename extension"
subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
return hasattr(module, subclass) and getattr(module, subclass) or FileInfo
[1] | 这是一个有两个参数的函数;filename 是必须的,但 module 是可选的并且 module 的缺省值包含了 FileInfo 类。这样看上去效率低,因为你可能认为 Python 会在每次函数调用时计算这个 `sys .modules表达式。实际上,Python 仅会对缺省表达式计算一次,是在模块导入的第一次。正如后面我们会看到的,我们永远不会用一个 module参数来调用这个函数,所以 module` 的功能是作为一个函数级别的常量。 |
[2] | 我们会在后面再仔细研究这一行,在我们了解了 os 模块之后。那么现在,只要相信 subclass 最终为一个类的名字就行了,像 MP3FileInfo 。 |
[3] | 你已经了解了 getattr ,它可以通过名字得到一个对象的引用。hasattr 是一个补充性的函数,用来检查一个对象是否具有一个特定的属性;在本例中,用来检查一个模块是否有一个特别的类 (然而它可以用于任何类和任何属性,就像 getattr )。用英语来说,这行代码是说,“If this module has the class named by subclass then return it, otherwise return the base class FileInfo (如果这个模块有一个名为 subclass 的类,那么返回它,否则返回基类 FileInfo )”。 |
进一步阅读
- Python Tutorial 讨论了缺省参数到底在什么时候和是如何计算的。
- Python Library Reference 提供了
sys
模块的文档。