Python从内存中使用编译后的模块

  在Windows编程的时候,有些时候,咱们常常会要使用一些很是规的方法,好比说从内存中加载DLL,而后使用DLL中的函数。因而就思索在用Python的时候是否可以将几个编译好的Pyc合并成一个,而后使用动态的读取这个文件,而后根据标记进行划分,得到不一样的模块的pyc内容,而后动态做为一个新的模块引用到咱们的程序中去,这就涉及到一个问题,如何将一个pyc整到内存,而后从内存中获取变成一个新模块进行引入处理。以后找了一些资料以后,发现一种方法,就是经过PyCodeObject这个代码对象来进行处理,也就是用compile编译以后的内容,而后读取造成codeobject对象,而后用types.ModuleType创建一个新的模块,而后将这个新模块加入到sys.modules字典中去,以后在这这个新建的模块环境中执行前面读取的codeObject对象,那么久可使用这个新的导入模块了,方式以下:python

#代码以下:
PycContext = open('test.pyo', 'rb').read()
import marshal
#能够查看PyCodeObject数据结构前面8个位是一个4字节MagicNum和4字节的时间戳,因此从第八位开始
PyCodeObject = marshal.loads(b[8:])
import types
#创建一个名字叫testSimple的新模块
newModule = types.ModuleType('testSimple')
import sys
sys.modules['testSimple'] = newModule
#这个时候已经能够用import testSimple了
#可是运行时候会发现,这个新模块什么功能函数都没有,由于尚未和
#上面的PyCodeObject关联起来,此时须要关联
#就是使用exec在本模块环境执行一次,则可
exec c in newModule.__dict__
#这样,上面的codeObject和新模块就关联起来了,而后就可使用里面的函数了

另外记录一个外国的资料代码以下编程

def load_compiled_from_memory(name, filename, data, ispackage=False):
    if data[:4]!=imp.get_magic():
        raise ImportError('Bad magic number in %s' % filename)
    # Ignore timestamp in data[4:8]
    code = marshal.loads(data[8:])
    imp.acquire_lock() # Required in threaded applications
    try:
        mod = imp.new_module(name)
        sys.modules[name] = mod # To handle circular and submodule imports 
                                # it should come before exec.
        try:
            mod.__file__ = filename # Is not so important.
            # For package you have to set mod.__path__ here. 
            # Here I handle simple cases only.
            if ispackage:
                mod.__path__ = [name.replace('.', '/')]
            exec code in mod.__dict__
        except:
            del sys.modules[name]
            raise
    finally:
        imp.release_lock()
    return mod

另外须要说明一下的是,使用Python import自动生成的编译后的文件通常都带有魔数和时间戳,也就是说读取codeObject的时候须要移动8位,可是有些用Python的API生成的不必定带有这个魔数和时间戳的,那么这个时候就不用移位,而直接读取生成codeobject数据结构

 

国外参考资料app

相关文章
相关标签/搜索