Qt+Boost嵌入Python模块后,外部脚本无法导入hello模块的问题
问题原因分析
你遇到的核心问题是混淆了嵌入式Python和独立Python进程的区别:
- 你在Qt应用里通过
PyImport_AppendInittab注册的hello模块,是绑定在Qt进程内部初始化的Python解释器实例里的。 - 而你在终端运行的
test_hilton.py是启动了一个完全独立的Python进程,这个进程的解释器根本不知道Qt进程里注册的模块,自然会报ModuleNotFoundError。
PyImport_AppendInittab的作用是给当前进程内的Python解释器添加内置模块,它不会把模块安装到系统Python环境或者当前目录的可导入路径里,所以外部Python进程无法访问。
解决办法
根据你的需求,有两种可行的方案:
方案1:将Boost.Python模块编译为独立共享库(推荐用于外部Python调用)
如果你的目标是让外部Python脚本能导入hello模块,那不需要在Qt应用里注册内置模块,而是把hello模块编译成Python可识别的共享库文件:
- 单独编写模块代码文件(比如
hello_module.cpp):
#include <boost/python.hpp> struct World { void set(std::string msg) { this->msg = msg; } std::string greet() { return msg; } std::string msg; }; BOOST_PYTHON_MODULE(hello) { namespace python = boost::python; python::class_<World>("World") .def("greet", &World::greet) .def("set", &World::set) ; }
用CMake或qmake编译成共享库,注意编译时要链接Python和Boost.Python库,并且生成的库文件名要符合Python模块规范(比如Linux下是
hello.so,Windows下是hello.pyd)。把生成的库文件放到终端Python的
sys.path可访问路径里(比如和测试脚本同目录),这样终端运行import hello就能成功了。
方案2:在Qt应用内部运行Python代码(适合嵌入式场景)
如果你的需求是在Qt应用里调用Python代码,而不是外部脚本独立运行,那可以在Qt的main函数里初始化Python后,直接执行你的测试代码:
修改main.cpp的Python初始化部分:
try { int uploaded = PyImport_AppendInittab("hello", &PyInit_hello); if(uploaded == -1) std::cout<< "Module table was not extended: " << uploaded << std::endl; else std::cout<< "Module Table was extended" << std::endl; Py_Initialize(); // 直接在Qt进程内运行Python代码 python::exec( "import hello\n" "w = hello.World()\n" "w.set('Hello from Qt embedded Python!')\n" "print(w.greet())" ); } catch (...) { PyErr_Print(); return 1; }
这样运行Qt应用时,就会在内部的Python解释器里执行代码,成功调用hello模块的方法。
额外注意事项
- 如果选择方案1,要确保编译模块时使用的Python版本和终端运行的Python版本一致,否则会出现兼容性问题。
- 对于Qt应用,如果你同时需要嵌入式Python和外部模块访问,可以同时实现两种方式,但要注意代码分离,避免混淆。
内容的提问来源于stack exchange,提问作者Hilton
相关产品推荐
相关产品推荐

