3.13. 更多关于模块

象Python中的其它东西一样,模块是对象。一旦导入,总是可以全局字典 sys.modules 来得到一个模块的引用。

例 3.30. sys.modules 介绍

>>> import sys                          1
>>> print '\n'.join(sys.modules.keys()) 2
win32api
os.path
os
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
1 这个 sys 模块包含了系统级的信息,象正在运行的Python的版本(sys.versionsys.version_info),和系统级选项,象最大允许递归的深度(sys.getrecursionlimit()sys.setrecursionlimit())。
2

sys.modules 是一个字典,它包含了从Python开始运行起被导入的所有模块。键字就是模块名,键值就是模块对象。请注意除了你的程序导入的模块外还有其它模块。Python在启动时预先装入了一些模块,如果你在一个Python IDE环境下,sys.modules 包含了你在IDE中运行的所有程序所导入的所有的模块。

例 3.31. 使用 sys.modules

>>> import fileinfo         1
>>> 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"] 2
<module 'fileinfo' from 'fileinfo.pyc'>
1 当导入新的模块,它们加入到 sys.modules 中。这就解释了为什么第二次导入相同的模块是非常的快:Python已经在 sys.modules 中装入和缓冲了,所以第二次导入仅仅对字典做了一个查询。
2 一旦给出任何以前导入过的模块名(以字符串方式),通过 sys.modules 字典,你可以得到对模块本身的一个引用。

例 3.32. __module__ 类属性

>>> from fileinfo import MP3FileInfo
>>> MP3FileInfo.__module__              1
'fileinfo'
>>> sys.modules[MP3FileInfo.__module__] 2
<module 'fileinfo' from 'fileinfo.pyc'>
1 每个Python类拥有一个内置的类属性 __module__,它是定义了这个类的模块的名字。
2 将它与 sys.modules 字典复合使用,你可以得到定义了某个类的模块的引用。

例 3.33. 在 fileinfo.py 中的 sys.modules

    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):       1
        "get file info class from filename extension"                             
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]        2
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfo 3
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)”。

进一步阅读