Python從內存中使用編譯后的模塊


  在Windows編程的時候,有些時候,我們經常會要使用一些非常規的方法,比如說從內存中加載DLL,然后使用DLL中的函數。於是就思索在用Python的時候是否能夠將幾個編譯好的Pyc合並成一個,然后使用動態的讀取這個文件,然后根據標記進行划分,獲得不同的模塊的pyc內容,然后動態作為一個新的模塊引用到我們的程序中去,這就涉及到一個問題,如何將一個pyc整到內存,然后從內存中獲取變成一個新模塊進行引入處理。之后找了一些資料之后,發現一種方法,就是通過PyCodeObject這個代碼對象來進行處理,也就是用compile編譯之后的內容,然后讀取形成codeobject對象,然后用types.ModuleType建立一個新的模塊,然后將這個新模塊加入到sys.modules字典中去,之后在這這個新建的模塊環境中執行前面讀取的codeObject對象,那么久可以使用這個新的導入模塊了,方式如下:

#代碼如下:
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

 

國外參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM