如何在Pybind11嵌入C++环境中导入pip安装的Python包?
Pybind11嵌入Python时导入site-packages包的问题解决
Pybind11完全支持导入Python site-packages中的第三方包,你遇到的numpy.core._multiarray_umath导入错误,本质是嵌入的Python解释器环境与你直接运行python命令的环境不一致导致的,以下是具体解决方法:
问题复现
你已成功运行简单嵌入示例:calc.py:
def say(): return "Hello world!"
main.cpp:
#include <iostream> #include <pybind11/embed.h> namespace py = pybind11; int main() { py::scoped_interpreter guard{}; try { py::module_ calc = py::module_::import("calc"); py::object result = calc.attr("say")(); py::print(result); } catch (py::error_already_set &e) { std::cout << e.what() << std::endl; } std::cin.get(); }
但在calc.py中添加import numpy后触发ImportError,直接运行python calc.py无异常。
解决方法
1. 匹配Python版本
numpy等编译型第三方包与Python版本强绑定,必须确保你的C++项目链接的Python库版本,和你运行python calc.py时的Python版本完全一致。
- 检查编译配置中指定的Python路径,确认是否为安装了numpy的那个版本。
2. 显式设置PYTHONHOME变量
在启动Python解释器前,设置PYTHONHOME指向你的目标Python环境路径,让嵌入的解释器能正确识别site-packages位置:
int main() { // 替换为你的Python环境路径,如Windows下"C:/Python39",Linux下"/usr/bin/python3.9" setenv("PYTHONHOME", "/path/to/your/python/env", 1); py::scoped_interpreter guard{}; try { // 可选:打印sys.path确认路径是否包含目标site-packages py::module_ sys = py::module_::import("sys"); py::print(sys.attr("path")); py::module_ calc = py::module_::import("calc"); py::object result = calc.attr("say")(); py::print(result); } catch (py::error_already_set &e) { std::cout << e.what() << std::endl; } std::cin.get(); }
3. 检查编译链接配置
- 若使用CMake,确保
find_package(Python REQUIRED)找到的是安装了numpy的Python版本,而非系统默认的其他版本。 - 手动编译时,需指定正确的Python头文件路径,并链接对应版本的Python库文件(如
python39.lib或libpython3.so)。
4. 虚拟环境适配
如果使用虚拟环境,除了设置PYTHONHOME外,还可手动将虚拟环境的site-packages路径添加到sys.path:
py::module_ sys = py::module_::import("sys"); sys.attr("path").attr("append")("/path/to/venv/lib/python3.9/site-packages");
内容的提问来源于stack exchange,提问作者Seung-Min Jung
相关产品推荐
相关产品推荐

