如何定制Python模块的查找和物理实现
一般来说,python从文件上的.py或者相应的字节码文件.pyc或.pyo获得一 个python module对象。有时候会需要定制这个过程,比方说,嵌入python作为 应用容器的时候,希望有一种特别的应用打包格式,类似jar或者war,或者处 于某些原因,需要改变python module的物理存储,比如,处于查找性能上的考 虑,如果python module能从一个key-value得到就好了,或者处于商务 上的原因,如果能对源代码(或者pyc,而pyc很容易被反编译到py)进行 处理就更好了。
3.1 如何获得一个module对象
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。
3.2 如何定制python module的查找
参考上面的链接。要点在于可以用一个实现了import protocol的class去 hook模块加载的过程,这个hook要被安装到sys.pathhooks.
这是一个从网络上(github)import模块的例子:
3.3 如何定制python module的存储
参考前面的代码,关键在于`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
推荐阅读
-
如何定制Python模块的查找和物理实现
-
Python3 加密(hashlib和hmac)模块的实现
-
C++如何实现python中的startswith和endswith
-
python-logging模块的简单使用:如何同时输出到控制台和本地日志文件
-
Python的包(package)和模块(module)的区别,如何导入python包和模块,以及为什么可以把包名当作一个模块导入
-
如何用Python和JS实现的Web SSH工具
-
python实现skywalking的trace模块过滤和报警(实例代码)
-
python 数据结构之二分查找的递归和普通实现
-
如何定制Python模块的查找和物理实现
-
Python程序员面试算法宝典---解题总结: 第4章 数组 4.2 如何查找数组中元素的最大值和最小值