【发布时间】:2017-06-11 00:29:18
【问题描述】:
假设我有一个这样的模块文件:
# 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)
欢迎任何帮助。
【问题讨论】:
-
my_module没有定义print(),这是 Python 3.x 中的内置函数。 -
@martineau 我不明白你的意思。我使用 Python 3,所以使用
print()没有定义它没有问题。 -
你说你想覆盖
print()函数,我只是指出它没有在你导入的模块中定义。 -
@martineau 我明白了,谢谢,确实我无法正确“覆盖”打印功能,我宁愿说我想对其进行猴子补丁。
-
另请注意,为
print()执行此操作可能与普通函数不同,因为它是内置函数。
标签: python python-3.x import mocking python-importlib