我正在嘗試使用基於PEP302的導入鉤子來捕獲模塊的導入,以便我可以在運行時加載一些加密的.py文件。我正在關注python混淆模板https://github.com/citrusbyte/python-obfuscation。需要PEP302實現細節
基本思想很簡單:使用插入到捕獲導入指令的sys.meta_path中的Finder()函數攔截導入命令。 Finder檢查模塊是否是我們想要處理的模塊,如果是,則返回一個自定義的Loader對象。否則它會忽略導入。自定義加載程序在sys.modules中創建一個條目,並讀入python模塊源文件,並使用PEP302文檔中定義的exec將其添加到新創建的模塊中。
這工作大多好,但我有一個具體的情況,我無法弄清楚。假設3個文件,main,foo和bar。主要設置導入鉤然後導入foo,並且吧。 foo本身進口吧。所以情況是:
main:
set_import_hook
import foo
import bar
foo:
import bar
bar:
<irrelevant>
我在Finder函數集中的調試語句設置爲鉤子以查看它正在傳遞。
當我有未加密的代碼(即代碼,我不處理,並加入到sys.modules中自己,打印輸出顯示以下行爲:
Finder (foo)
Finder (bar) called from inside foo when foo itself is loaded
Finder (bar) called from main after returning from the import foo
當我處理並加載foo和bar文件我,這裏是行爲:
Finder (foo)
Finder (foo.bar) tries to load bar in the context of foo
Finder (bar) called from main after returning from import foo
這將導致酒吧sys.modules中存在的兩個版本。如果你看一下在兩種情況下sys.modules.keys(),在第一種情況下它只能說明foo和bar。第二種情況顯示foo,foo.bar和bar。
我不明白這種行爲。創建模塊的過程如PEP 302文檔中所述。這是我使用的:
module = sys.modules.setdefault(name, imp.new_module(name))
module.__file__ = filename
module.__path__ = [os.path.dirname(os.path.abspath(file.name))]
module.__loader__ = self
sys.modules[name] = module
exec(src, module.__dict__)
謝謝。