如何覆盖 Python 导入? [英] How do I override a Python import?

查看:11
本文介绍了如何覆盖 Python 导入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究 pypreprocessor 这是一个采用 c 风格指令和我已经能够让它像传统的预处理器一样工作(它是自我消耗的,并在运行中执行后处理代码),只是它会破坏库导入.

I'm working on pypreprocessor which is a preprocessor that takes c-style directives and I've been able to make it work like a traditional preprocessor (it's self-consuming and executes postprocessed code on-the-fly) except that it breaks library imports.

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

The problem is: The preprocessor runs through the file, processes it, outputs to a temporary file, and exec() the temporary file. Libraries that are imported need to be handled a little different, because they aren't executed, but rather they are loaded and made accessible to the caller module.

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

What I need to be able to do is: Interrupt the import (since the preprocessor is being run in the middle of the import), load the postprocessed code as a tempModule, and replace the original import with the tempModule to trick the calling script with the import into believing that the tempModule is the original module.

到目前为止,我已经到处搜索,但没有解决方案.

I have searched everywhere and so far and have no solution.

这个堆栈溢出问题是迄今为止我见过的最接近提供答案的问题:覆盖 Python 中的命名空间

This Stack Overflow question is the closest I've seen so far to providing an answer: 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 是后处理代码文件的名称.

moduleName is the name of the original module, and tmpModuleName is the name of the postprocessed code file.

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

The strange part is this solution still runs completely normal as if the first module completed loaded normally; unless you remove the last line, then you get a module not found error.

希望 StackOverflow 上的某个人比我更了解导入,因为这个让我难住了.

Hopefully someone on Stack Overflow know a lot more about imports than I do, because this one has me stumped.

注意:我只会奖励一个解决方案,或者,如果这在 Python 中是不可能的;关于为什么这不是不可能的最好、最详细的解释.

更新:对于任何感兴趣的人,这里是工作代码.

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

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

The 'imp.lock_held' part detects whether the module is being loaded as a library. The following lines do the rest.

推荐答案

这是否回答了您的问题?第二个导入可以解决问题.

Does this answer your question? The second import does the trick.

Mod_1.py

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

Mod_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 导入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆