如何覆盖Python导入?

时间:2010-06-10 07:33:16

标签: python import preprocessor override

我正在研究pypreprocessor这是一个采用c风格指令的预处理器,我已经能够使它像传统的预处理器一样工作(它是自我消耗的并且在上面执行后处理代码)除了它打破了图书馆的进口外。

问题是:预处理器运行文件,处理它,输出到临时文件,exec()临时文件。导入的库需要处理稍微不同,因为它们不会被执行,而是被加载并且可以被调用者模块访问。

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

到目前为止,我到处搜索并且没有解决方案。

这个Stack Overflow问题是我到目前为止提供答案的最接近的问题: Override namespace in Python

这就是我所拥有的。

# Remove the bytecode file created by the first import
os.remove(moduleName + '.pyc')

# Remove the first import
del sys.modules[moduleName]

# Import the postprocessed module
tmpModule = __import__(tmpModuleName)

# Set first module's reference to point to the preprocessed module
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'部分检测模块是否作为库加载。以下几行完成其余的工作。

4 个答案:

答案 0 :(得分:35)

这是否回答了你的问题?第二个导入就是诀窍。

Mod_1.py

def test_function():
    print "Test Function -- Mod 1"

Mod_2.py

def test_function():
    print "Test Function -- Mod 2"

Test.py

#!/usr/bin/python

import sys

import Mod_1

Mod_1.test_function()

del sys.modules['Mod_1']

sys.modules['Mod_1'] = __import__('Mod_2')

import Mod_1

Mod_1.test_function()

答案 1 :(得分:12)

要定义不同的导入行为或完全破坏导入过程,您需要编写导入钩子。请参阅PEP 302

例如,

import sys

class MyImporter(object):

    def find_module(self, module_name, package_path):
        # Return a loader
        return self

    def load_module(self, module_name):
        # Return a module
        return self

sys.meta_path.append(MyImporter())

import now_you_can_import_any_name
print now_you_can_import_any_name

输出:

<__main__.MyImporter object at 0x009F85F0>

所以基本上它返回一个新模块(可以是任何对象),在这种情况下本身。您可以通过在导入processe_xxx时返回xxx来改变导入行为。

IMO:Python不需要预处理器。无论你正在完成什么,都可以在Python本身完成,因为它非常动态,例如,以调试示例为例,在文件顶部有什么问题

debug = 1

以后

if debug:
   print "wow"

答案 2 :(得分:1)

在Python 2中,imputil模块似乎提供了您正在寻找的功能,但已在python 3中删除。它没有很好的文档,但包含一个示例部分,说明如何替换标准导入功能。

对于Python 3,有importlib模块(在Python 3.1中引入),其中包含用于以各种方式修改导入功能的函数和类。将预处理器挂钩到导入系统应该是合适的。

答案 3 :(得分:-3)

非常奇怪的方法 - 用高级语言模拟低级语言。如果第一种简单的方法不起作用,可能是一个错误的目标?

BTW,C预处理器只使用文本文件和一组预处理器变量,而不是高级加载/卸载模块。