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

相關文章
相關標籤/搜索