如何定制Python模块的查找和物理实现

如何定制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的查找

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

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 <[email protected]>

Date: 2012-03-20 Tue

HTML generated by org-mode 6.33x in emacs 23

 

你可能感兴趣的:(如何定制Python模块的查找和物理实现)