You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不修改原代码的前提下Monkey Patch导入时执行的函数?

解决方案

核心思路是在包A被导入之前,先对包B中的函数c进行Monkey Patch,这样当A导入时执行的就是被替换后的dummy函数,而非原函数。以下是具体实现方式:

1. 先Patch B的c再导入A

直接在测试函数中调整顺序,先通过monkeypatch修改B模块的c,再导入A:

def test(monkeypatch):
    # 先patch包B中的c函数
    monkeypatch.setattr("B.c", lambda: "dummy")
    # 此时再导入A,执行的是已patch后的c
    import A
    # 后续编写测试逻辑

2. 利用测试框架的前置Fixture确保提前Patch

如果使用pytest,可以定义一个自动执行的会话级Fixture,在所有测试开始前完成Patch并导入A:

import pytest
from unittest.mock import patch

@pytest.fixture(autouse=True, scope="session")
def pre_patch_and_import():
    with patch("B.c", return_value="dummy"):
        import A
        yield A

后续测试函数可直接使用该Fixture,确保A始终在Patch后被导入。

3. 清除模块缓存(解决模块已被提前导入的情况)

如果测试过程中A或B已被意外导入,可先清除sys.modules中的缓存,再重新Patch并导入:

import sys

def test(monkeypatch):
    # 清除已导入的A和B模块缓存
    for mod_name in ["A", "B"]:
        if mod_name in sys.modules:
            del sys.modules[mod_name]
    # 重新patch B的c
    monkeypatch.setattr("B.c", lambda: "dummy")
    # 再次导入A
    import A
    # 执行测试

原理说明

包A中from B import c的逻辑会在A被导入时执行:

  • 若先Patch B的c,A会引用并执行这个被替换后的函数;
  • 若先导入A再Patch A的c,此时原c已经执行完毕,Patch仅替换A模块中c的引用,无法改变已经执行过的代码结果。

内容的提问来源于stack exchange,提问作者ChiPlusPlus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:01:46