我正在尝试使用基于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__)
谢谢。