如何覆盖Python的导入?

11 浏览
0 Comments

如何覆盖Python的导入?

我正在开发一个名为pypreprocessor的预处理器,它可以接受C风格的指令。我已经成功将其运作得像传统的预处理器一样(它是自消耗的,并且可以实时执行后处理的代码),只是它会破坏库的导入。

问题是:预处理器会遍历文件,进行处理,输出到一个临时文件,然后使用exec()执行临时文件。导入的库需要稍微处理一下,因为它们不会被执行,而是载入并使其对调用模块可访问。

我需要做的是:中断导入(因为预处理器在导入过程中运行),将后处理的代码作为临时模块加载,并将原始导入替换为临时模块,以欺骗调用脚本的导入部分,使其认为临时模块是原始模块。

我已经到处搜索了,但是目前还没有找到解决方案。

这个Stack Overflow的问题是我目前看到的最接近提供答案的:

Override namespace in Python

这是我的代码。

# 删除第一个导入创建的字节码文件
os.remove(moduleName + '.pyc')
# 删除第一个导入
del sys.modules[moduleName]
# 导入后处理的模块
tmpModule = __import__(tmpModuleName)
# 将第一个模块的引用指向预处理的模块
sys.modules[moduleName] = tmpModule

moduleName是原始模块的名称,tmpModuleName是后处理代码文件的名称。

奇怪的是,这个解决方案仍然完全正常运行,就好像第一个模块正常加载完成一样;除非删除最后一行,然后会出现模块找不到的错误。

希望Stack Overflow上的某个人在导入方面比我更了解,因为这个问题让我困惑。

注意:我只会授予一个解决方案,或者如果在Python中不可能实现的话,提供最好、最详细的解释。

更新:对于任何感兴趣的人,这是可行的代码。

if imp.lock_held() is True:
    del sys.modules[moduleName]
    sys.modules[tmpModuleName] = __import__(tmpModuleName)
    sys.modules[moduleName] = __import__(tmpModuleName)

'imp.lock_held'部分检测模块是否作为库加载。接下来的几行完成剩下的工作。

0