嵌入式Python无法找到dist-packages依赖包问题求助
在Ubuntu 22.04系统的C++ CMake项目中嵌入Python 3.10应用,已安装python-dev。相关配置与代码如下:
CMakeLists.txt
cmake_minimum_required(VERSION 3.21) project(MyPythonEmbeddedApp) find_package(Python3 3.10 REQUIRED COMPONENTS Interpreter Development) add_executable(my_app src/main.cpp) target_include_directories(my_app PRIVATE ${Python_INCLUDE_DIRS}) target_link_libraries(my_app Python3:python)
main.cpp
#include "Python.h" #include <iostream> int main(int argc, char** argv) { Py_Initialize(); // ./ is the path to myPythonModule.py // Must add /usr/lib/python3.10 or can't find any base python modules in script // Adding location to dist-packages makes valkka-onvif found PySys_SetPath(L"./:/usr/lib/python3.10:/usr/local/lib/python3.10/dist-packages/"); PyObject* pythonModule = PyImport_ImportModule("myPythonModule"); Py_DECREF(pythonModule); Py_Finalize(); return 0; }
myPythonModule.py
from valkka.onvif import OnVif, DeviceIO, DeviceManagement, getWSDLPath class OnvifClass(OnVif): serial_port = [] def __init__(self, ip="172.25.0.100", port=8000, user="", password=""): self.ip = ip self.port = port print("Initialized Handler")
运行时出现错误:FATAL: you are importing valkka.onvif, but don't have zeep installed. Please install zeep with pip install zeep,该提示来自/usr/local/lib/python3.10/dist-packages/valkka/onvif/base.py对zeep的导入。
已通过sudo pip3 install valkka-onvif安装包到/usr/local目录,同时安装了指定版本zeep==4.0.0,两个包均位于/usr/local/lib/python3.10/dist-packages/。命令行运行该Python模块无问题,但嵌入式运行时依赖找不到。
1. 修复PySys_SetPath的使用方式
直接调用PySys_SetPath会完全覆盖Python默认的sys.path,导致部分依赖包的路径丢失。正确做法是在原有路径基础上追加自定义路径:
修改main.cpp中的路径设置部分:
Py_Initialize(); // 获取原有sys.path PyObject* sysPath = PySys_GetObject((char*)"path"); // 追加自定义路径 PyList_Append(sysPath, PyUnicode_FromString("./")); PyList_Append(sysPath, PyUnicode_FromString("/usr/local/lib/python3.10/dist-packages/")); // 原有的/usr/lib/python3.10通常已经在默认path中,无需重复添加
2. 修正CMake配置中的变量错误
- 变量名
Python_INCLUDE_DIRS应为Python3_INCLUDE_DIRS(对应find_package(Python3 ...)) - 链接库的写法应为
Python3::Python(双冒号是CMake标准的目标链接语法)
修正后的CMakeLists.txt:
cmake_minimum_required(VERSION 3.21) project(MyPythonEmbeddedApp) find_package(Python3 3.10 REQUIRED COMPONENTS Interpreter Development) add_executable(my_app src/main.cpp) target_include_directories(my_app PRIVATE ${Python3_INCLUDE_DIRS}) target_link_libraries(my_app Python3::Python)
3. 验证嵌入式Python环境与命令行一致性
在main.cpp中添加代码,打印当前Python的可执行路径和sys.path,确认与命令行python3的环境一致:
// 在Py_Initialize()后添加 PyObject* sysModule = PyImport_ImportModule("sys"); PyObject* executable = PyObject_GetAttrString(sysModule, "executable"); PyObject* path = PyObject_GetAttrString(sysModule, "path"); // 打印executable const char* execStr = PyUnicode_AsUTF8(executable); std::cout << "Python executable: " << execStr << std::endl; // 打印sys.path Py_ssize_t pathLen = PyList_Size(path); std::cout << "sys.path:" << std::endl; for (Py_ssize_t i = 0; i < pathLen; ++i) { PyObject* item = PyList_GetItem(path, i); const char* itemStr = PyUnicode_AsUTF8(item); std::cout << " " << itemStr << std::endl; } Py_DECREF(sysModule); Py_DECREF(executable); Py_DECREF(path);
运行程序后对比命令行python3 -c "import sys; print(sys.executable); print(sys.path)"的输出,确保路径一致。
4. 确认zeep包的安装路径
如果zeep安装在其他路径(比如用户目录~/.local/lib/python3.10/site-packages/),需要将该路径也追加到sys.path中。可以通过命令查看安装位置:
pip3 show zeep
输出中的Location字段即为zeep的安装路径,将其添加到main.cpp的sys.path追加列表中。
内容的提问来源于stack exchange,提问作者notARobot

