使用Pybind11跨文件导入模块时遭遇ModuleNotFoundError
问题分析与解决
你的问题核心在于编译方式错误,导致base_class模块并未实际生成,而derived_class绑定代码里又尝试导入这个不存在的模块,从而触发ModuleNotFoundError。另外你的C++代码还有几处语法错误需要修正。
第一步:修正C++代码中的语法问题
- base_class.h:修复构造函数初始化列表语法,补充类定义末尾分号
// base_class.h class BaseClass { public: BaseClass(int id): id(id) {} // 移除多余的int关键字 int get_id() { return id; } private: int id; }; // 类定义末尾必须添加分号
- derived_class.h:修正头文件引用路径并补充分号
// derived_class.h #include "common/base_class.h" // 补充.h后缀,路径需匹配实际文件结构 class DerivedClass: public BaseClass { public: DerivedClass(int id); }; // 类定义末尾添加分号
第二步:拆分编译,生成独立扩展模块
按照pybind11跨模块拆分的设计要求,你需要分别编译base_class和derived_class两个独立的共享对象文件:
编译base_class模块
g++ -std=c++20 -shared -fpic `python3.12 -m pybind11 --includes` common/base_class_binding.cpp -o base_class.so
编译derived_class模块
g++ -std=c++20 -shared -fpic `python3.12 -m pybind11 --includes` derived_class.cpp derived_class_binding.cpp -o derived_class.so
第三步:调整Python测试代码
确保生成的两个.so文件和test.py在同一目录下,修改测试代码如下(显式导入基类模块可避免导入顺序问题):
# test.py import base_class from derived_class import DerivedClass if __name__ == '__main__': derived_obj = DerivedClass(1) print(f'The ID is: {derived_obj.get_id()}')
为什么之前的方法行不通?
- 错误的编译命令:你把
base_class_binding.cpp和derived_class的代码打包到同一个.so中,但每个PYBIND11_MODULE会生成独立的Python模块入口,这会导致两个模块定义冲突,最终只有derived_class模块被识别,base_class模块根本不存在,自然无法导入。 - 重复定义基类绑定:虽然重复定义
py::class_<BaseClass>能临时运行,但违背了跨模块拆分的初衷,会带来代码冗余和维护隐患。
额外注意事项
- 如果两个
.so不在Python默认搜索路径,需手动添加路径:import sys sys.path.append("/path/to/your/modules") - 绑定代码中
py::module_::import("base_class")的模块名必须和生成的.so文件名完全一致(大小写敏感)。
内容的提问来源于stack exchange,提问作者stryker14
相关产品推荐
相关产品推荐

