Python 的模块导入原理
James Bennett 在他的 blog(B-List) 上最近发表了两篇文章(1, 2),谈到了 Python 中的一些 'Magic'. 其中提到所谓的‘克拉克第三定律’:
Any sufficiently advanced technology is indistinguishable from magic.
(任何足够高级的技术都近乎魔术)
Django 在 0.95 版本之前,就包含了不少魔术,然而这被认为是“违法直觉的”,而在后续的版本中被去除了。可见,Python 中的好的设计还是倾向于简单,遵循直觉。不过,研究这些手段,有助于我们更深入的理解 Python 的某些高级特性,从而更好的掌控这个语言。
其中,文中提到的例子讲述了模块导入的原理,以及如何利用这个原理实现魔术一样的效果:
比如自己定义一个模块,然后在 Django 框架中,可以从 Django 的包中导入它:
该技术的实质原理,涉及两点:
1. Python 模块只是普通对象,存在 sys.modules 这个字典中。
因此,可以向字典中自己增加一个项,用来注册动态创建的模块对象。然后就可以像普通模块一样被 import 了。
2.可以动态创建模块对象,利用 types 模块的一些方法实现。这个就类似于 .NET 的反射/CodeDOM:
>>> import types
>>> hello_mod = types.ModuleType('hello')
下面就可以向 hello_mod 这个动态创建的 module 附加任何属性或者函数,类等。
Any sufficiently advanced technology is indistinguishable from magic.
(任何足够高级的技术都近乎魔术)
Django 在 0.95 版本之前,就包含了不少魔术,然而这被认为是“违法直觉的”,而在后续的版本中被去除了。可见,Python 中的好的设计还是倾向于简单,遵循直觉。不过,研究这些手段,有助于我们更深入的理解 Python 的某些高级特性,从而更好的掌控这个语言。
其中,文中提到的例子讲述了模块导入的原理,以及如何利用这个原理实现魔术一样的效果:
比如自己定义一个模块,然后在 Django 框架中,可以从 Django 的包中导入它:
>>> from django.models.blog import entries这里 from 后面显示的并非实际模块定义的路径,而是动态产生。Django 读取你定义的模块,把它重新放到 django.models.blog 下面。
该技术的实质原理,涉及两点:
1. Python 模块只是普通对象,存在 sys.modules 这个字典中。
因此,可以向字典中自己增加一个项,用来注册动态创建的模块对象。然后就可以像普通模块一样被 import 了。
2.可以动态创建模块对象,利用 types 模块的一些方法实现。这个就类似于 .NET 的反射/CodeDOM:
>>> import types
>>> hello_mod = types.ModuleType('hello')
下面就可以向 hello_mod 这个动态创建的 module 附加任何属性或者函数,类等。