当前位置: 首页 > 面试题库 >

如何即时修改导入的源代码?

秋煌
2023-03-14
问题内容

假设我有一个像这样的模块文件:

# my_module.py
print("hello")

然后,我有一个简单的脚本:

# my_script.py
import my_module

这将打印"hello"

假设我想“覆盖”该print()函数,以使其返回"world"。我该如何以编程方式执行此操作(无需手动修改my_module.py)?

我以为是my_module在导入之前或导入时需要某种方式修改源代码。显然,导入后无法执行此操作,因此unittest.mock无法使用解决方案。

我还认为我可以读取文件my_module.py执行修改然后加载它。但这很丑陋,因为如果模块位于其他位置,它将无法正常工作。

我认为,好的解决方案是利用importlib

我阅读了文档,发现了一个非常交叉的方法:get_source(fullname)。我以为我可以覆盖它:

def get_source(fullname):
    source = super().get_source(fullname)
    source = source.replace("hello", "world")
    return source

不幸的是,我对所有这些抽象类有些迷惑,而且我不知道如何正确执行此操作。

我徒劳地尝试:

spec = importlib.util.find_spec("my_module")
spec.loader.get_source = mocked_get_source
module = importlib.util.module_from_spec(spec)

请任何帮助。


问题答案:

根据这篇精彩演讲的内容,这是我共同构思的解决方案。允许在导入指定模块之前对源进行任何任意修改。只要幻灯片没有忽略任何重要内容,它应该是合理正确的。这仅适用于Python
3.5+。

import importlib
import sys

def modify_and_import(module_name, package, modification_func):
    spec = importlib.util.find_spec(module_name, package)
    source = spec.loader.get_source(module_name)
    new_source = modification_func(source)
    module = importlib.util.module_from_spec(spec)
    codeobj = compile(new_source, module.__spec__.origin, 'exec')
    exec(codeobj, module.__dict__)
    sys.modules[module_name] = module
    return module

所以,用这个你可以

my_module = modify_and_import("my_module", None, lambda src: src.replace("hello", "world"))


 类似资料:
  • 问题内容: 我正在使用Pythonselenium来自动化我的出勤记录。一切正常,现在我想尝试通过修改源代码来尝试。我见过几篇文章,指出可以使用它对其进行修改并且适用于JavaScript,但就我而言,我需要在标记下修改源代码。我可以使用修改源代码。以下是标签的源代码: 我试图做到这一点。以下是我的代码: 但是上面的代码给了我以下错误: selenium.common.exceptions.Web

  • 我正在使用Python selenium来自动化我的考勤输入。它的工作很好,现在我想尝试修改源代码。我看到很少的帖子说明可以使用修改它,并且它适用于JavaScript,但是在我的例子中,我需要修改标记下的源代码。我能够使用修改源代码。以下是标记的源代码: 我尝试使用来实现。下面是我的代码: 但上面的代码给了我以下错误: selenium.common.exceptions.WebDriverEx

  • 问题 你想给某个已存在模块中的函数添加装饰器。 不过,前提是这个模块已经被导入并且被使用过。 解决方案 这里问题的本质就是你想在模块被加载时执行某个动作。 可能是你想在一个模块被加载时触发某个回调函数来通知你。 这个问题可以使用10.11小节中同样的导入钩子机制来实现。下面是一个可能的方案: # postimport.py import importlib import sys from coll

  • 问题内容: 当我使用Eclipse重新格式化代码时,它会变成这样的方法标题: 变成这样的方法标题: 当我来到这里时,我以前从未使用过Eclipse,而是导入了其他人提供的项目设置。我已经看到在我使用Eclipse的小型新项目中没有这样做,因此它必须在我导入的设置中。但是我已经遍历了所有可以找到的面板,以及我可以在工作区中找到的每个隐藏文件,而且我不知道是什么原因造成的。 如何关闭它?我不希望在方法

  • 有没有人知道该怎么做?我在IntelliJ IDEA中读到了导入Maven依赖项,但它并不起作用。谢谢

  • 问题内容: 我的数据以以下格式存储(向下看):[-]表示空白单元格,右边可能只有10列(空格后)。像这样的东西: [string0] [-] [string1] [string2] [string3] .. [string10] [-] 如何为以下代码更改此代码: 1)仅获取[string0] 2)仅获取[string1] [string2] [string3] .. [string10] [-]