如何覆盖Python的导入?

2024-05-14 04:26:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在研究pypreprocessor,这是一个接受c风格指令的预处理器,我已经能够使它像传统的预处理器一样工作(它是自用的,并且可以动态执行后处理代码),只是它中断了库导入。

问题是:预处理器在文件中运行,处理它,输出到临时文件,然后exec()临时文件。导入的库需要进行一些不同的处理,因为它们不会被执行,而是被加载并可供调用方模块访问。

我需要做的是:中断导入(因为预处理器正在导入的中间运行),将后处理代码加载为tempModule,并用tempModule替换原始导入,以诱使调用脚本相信tempModule是原始模块。

我到处都找了,到目前为止还没有找到解决办法。

这个堆栈溢出问题是迄今为止我看到的最接近于提供答案的问题: 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

module name是原始模块的名称,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\u hold”部分检测模块是否作为库加载。其余的行由下面的行来完成。


Tags: 模块文件the代码importmodulessys处理器
3条回答

要定义不同的导入行为或完全颠覆导入过程,您需要编写导入挂钩。见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>

所以基本上它返回一个新的模块(可以是任何对象),在本例中就是这样。您可以使用它在导入xxx时返回processe_xxx,从而更改导入行为。

IMO:Python不需要预处理器。由于Python本身的动态特性,您正在完成的任何事情都可以在Python中完成,例如,以debug为例,在文件顶部设置

debug = 1

后来

if debug:
   print "wow"

是吗?

这能回答你的问题吗?第二次进口就成功了。

模型1.py

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

模型2.py

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

测试.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()

在Python 2中有一个^{}模块,它似乎提供了您正在寻找的功能,但是在Python 3中已经被删除了。它没有很好的文档记录,但是包含一个示例部分,展示了如何替换标准导入函数。

对于Python 3,有一个^{}模块(在python3.1中引入),它包含以各种方式修改导入功能的函数和类。它应该适合将预处理器挂接到导入系统中。

相关问题 更多 >