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

使用pybind11嵌入Python解释器时如何清除模块缓存?

解决pybind11嵌入Python时动态切换同名模块的问题

问题根源

Python解释器会将已加载的模块缓存到sys.modules字典中,即使修改sys.path并调用importlib.invalidate_caches(),再次import同名模块时仍会直接读取该缓存,而非重新从文件系统加载。invalidate_caches()仅用于刷新Python对模块文件的查找缓存,不会清除已加载的模块实例。

解决方案

要实现动态切换同名模块,需在切换路径时同时清除sys.modules中对应模块的缓存,确保下次import时重新加载新路径下的模块。

修改后的代码示例

#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
namespace py = pybind11;

void addModulePath(const std::string &module) {
    auto sys = py::module::import("sys");
    auto importlib = py::module::import("importlib");
    auto path = sys.attr("path");

    path.attr("append")(module);
    importlib.attr("invalidate_caches")();
}

void deleteModulePath(std::string& module) {
    auto sys = py::module::import("sys");
    auto importlib = py::module::import("importlib");
    auto path = sys.attr("path");

    path.attr("remove")(module);
    importlib.attr("invalidate_caches")();
}

void clearModuleCache(const std::string& moduleName) {
    auto sys = py::module::import("sys");
    auto modules = sys.attr("modules");
    // 检查模块是否在缓存中,存在则移除
    if (py::hasattr(modules, moduleName)) {
        modules.attr("pop")(moduleName);
    }
}

PYBIND11_EMBEDDED_MODULE(changeModule, m) {
    m.def("add_module", &addModulePath, "add module path");
    m.def("delete_module", &deleteModulePath, "delete module path");
    m.def("clear_module_cache", &clearModuleCache, "clear specified module from sys.modules");
}

int main() {
    constexpr auto test1Path = "/tmp/test1";
    constexpr auto test2Path = "/tmp/test2";

    py::scoped_interpreter guard{};
    py::module_ module = py::module_::import("changeModule");

    // 加载第一个路径的test模块
    module.attr("add_module")(test1Path);
    auto test = py::module_::import("test");
    test.attr("test")();

    // 清理旧路径和模块缓存
    module.attr("delete_module")(test1Path);
    module.attr("clear_module_cache")("test");

    // 加载第二个路径的test模块
    module.attr("add_module")(test2Path);
    test = py::module_::import("test");
    test.attr("test")();

    return 0;
}

配套Python模块示例

/tmp/test1/test.py:

def test():
    print("Running test from /tmp/test1")

/tmp/test2/test.py:

def test():
    print("Running test from /tmp/test2")

关键修改说明

  • 新增clearModuleCache函数:负责检查并移除sys.modules中指定模块的缓存条目
  • 在删除旧模块路径后、添加新路径前调用该函数,确保已加载的test模块被完全清除
  • 再次执行import test时,Python会重新遍历当前sys.path,加载新路径下的模块文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 19:50:55