显式的定义一个加载函数
import imp
import sys
def load_module(module_name, module_content):
if fullname in sys.modules:
return sys.modules[fullname]
mod = sys.modules.setdefault(url, imp.new_module(module_name))
mod.__file__ = module_name
mod.__package__ = ''
# if *.py
code = compile(module_content, url, 'exec')
# if *.pyc 有问题,我运行一直报错
# code = marshal.loads(module_content[8:])
exec(code, mod.__dict__)
# 2的写法是 exec code in mod.__dict__
# 其实就是让code在环境里运行一下,所以这里可能会有注入漏洞
return mod
这个函数接受模块的名字和源码内容,并使用 compile() 将其编译到一个代码对象中, 然后在一个新创建的模块对象的字典中来执行它。
下面是这个函数的使用方式:
In[1]: module_content = open('tests/data_used_to_test.py').read()
In[2]: mod = load_module('test_import', module_content)
后面就和 1.4 一样了。
这样可以同时解决 1.3 中提出的两个问题。
因为你是先将源码作为普通文件读进来的,也就可以做各种修改后再注册到sys.modules中。
Pocsuite使用的就是这种方法。虽然我觉得他们当时可能也没太弄明白。
当然这还是有不足的。
上面的两种方法都只支持简单的模块。并没有嵌入到通常的import语句中。并不支持更高级的结构比如包。
不够酷