是时候了
In [1]: import imp
In [3]: m = imp.new_module("test")
In [4]: code_obj = compile("import os", "test.py", 'exec')
In [5]: code_obj
Out[5]: <code object <module> at 0x31b5830, file "test.py", line 1>
In [6]: exec code_obj in m.__dict__
In [7]: m
Out[7]: <module 'test' (built-in)>
In [8]: dir(m)
Out[8]: ['__builtins__', '__doc__', '__name__', '__package__', 'os']
这里面,newmodule调用创建了一个相应的module对象,内置函数compile则从 一个字符串(源码)获得了相应的code object,该object可以被exec。
http://www.python.org/dev/peps/pep-0302/
参考上面的链接。要点在于可以用一个实现了Import Protocol的class去 hook模块加载的过程,这个hook要被安装到sys.pathhooks.
这是一个从网络上(github)import模块的例子:
https://github.com/mitsuhiko/badideas/blob/master/githubimporter.py
参考前面的代码,关键在于`exec source in m._dict_`这里,source可以 是一段源码,比如"import os",也可以是一个code object,这个code object是可以被序列化和反序列化的,事实上,pyc就是该对象的序列化(加 上时间戳、magic number和crc校验),为了性能上的考虑,反序列化要比重 编译py源文件略好,可以把code object的序列化结果存储下来。在Importer 那里从该存储设备获取code object marshal string就行了。
•.从一个py文件获得其code object marshal string
import marshal
source = open("test.py").read()
co = compile(source, "test.py", 'exec')
co_s = marshal.dumps(co)
•.从一个code object marshal string获得一个python module
import marshal,imp
def load_module(co_str):
m = imp.new_module("test")
co = marshal.loads(co_str)
exec co in m.__dict__
return m
Author: MaTao <qingant@gmail.com>
Date: 2012-03-20 Tue
HTML generated by org-mode 6.33x in emacs 23
posted on 2012-09-02 04:27 qingant 阅读(1797) 评论(0) 编辑 收藏 引用