使用Python C API时遭遇ModuleNotFoundError问题求助
解决Python C API中ModuleNotFoundError的问题
错误原因分析
你遇到的ModuleNotFoundError有两个核心原因:
PyImport_Import参数错误:这个函数要求传入Python模块名(不带.py后缀,不能是完整文件路径),你传入的/home/user_1/project/ml/multiply.py会被Python当成完整模块名搜索,自然找不到匹配项。- 模块搜索路径未包含目标目录:Python默认的
sys.path里没有你的项目目录/home/user_1/project/ml,即便用正确模块名,Python也无法定位到该模块。
解决方案
1. 修改C++代码,正确配置搜索路径并导入模块
修改后的代码关键部分已标注:
#define PY_SSIZE_T_CLEAN #include <Python.h> int main(int argc, char *argv[]) { PyObject *pName, *pModule, *pFunc; PyObject *pArgs, *pValue, *sysPath; int i; if (argc < 3) { fprintf(stderr,"Usage: call pythonfile funcname [args]\n"); return 1; } Py_Initialize(); // 获取sys.path对象,将项目目录添加到搜索路径 sysPath = PySys_GetObject((char*)"path"); if (sysPath == NULL) { fprintf(stderr, "Failed to get sys.path\n"); return 1; } PyObject* projectDir = PyUnicode_FromString("/home/user_1/project/ml"); if (PyList_Append(sysPath, projectDir) != 0) { fprintf(stderr, "Failed to add directory to sys.path\n"); Py_DECREF(projectDir); return 1; } Py_DECREF(projectDir); // 传入模块名(不带.py后缀,即multiply) pName = PyUnicode_FromString(argv[1]); if (!pName) { fprintf(stderr, "Failed to create module name object\n"); return 1; } pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule != NULL) { pFunc = PyObject_GetAttrString(pModule, argv[2]); /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { pArgs = PyTuple_New(argc - 3); for (i = 0; i < argc - 3; ++i) { pValue = PyLong_FromLong(atoi(argv[i + 3])); if (!pValue) { Py_DECREF(pArgs); Py_DECREF(pModule); fprintf(stderr, "Cannot convert argument\n"); return 1; } /* pValue reference stolen here: */ PyTuple_SetItem(pArgs, i, pValue); } pValue = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); if (pValue != NULL) { printf("Result of call: %ld\n", PyLong_AsLong(pValue)); Py_DECREF(pValue); } else { Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); fprintf(stderr,"Call failed\n"); return 1; } } else { if (PyErr_Occurred()) PyErr_Print(); fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); } Py_XDECREF(pFunc); Py_DECREF(pModule); } else { PyErr_Print(); fprintf(stderr, "Failed to load \"%s\"\n", argv[1]); return 1; } if (Py_FinalizeEx() < 0) { return 120; } return 0; }
2. 修正编译命令
原命令中-L参数缺少根路径/,且-lpython指定具体版本可避免冲突,修正后:
g++ testcapi.cpp -I /usr/include/python3.10 -L /usr/lib/python3.10 -lpython3.10 -o a
3. 正确运行程序
保持原运行命令即可,此时argv[1]是正确的模块名:
./a multiply multiply 3 2
替代方案:直接加载Python脚本文件
若不想用模块导入方式,也可直接加载脚本执行,核心代码片段如下:
// 替换原PyImport_Import部分 FILE* fp = fopen("/home/user_1/project/ml/multiply.py", "r"); if (!fp) { fprintf(stderr, "Failed to open script file\n"); return 1; } // 执行脚本,将函数加载到全局命名空间 PyRun_SimpleFile(fp, "/home/user_1/project/ml/multiply.py"); fclose(fp); // 获取全局命名空间中的函数 pFunc = PyObject_GetAttrString(PyImport_GetModuleDict(), "multiply"); // 后续调用逻辑不变
内容的提问来源于stack exchange,提问作者catfriendly
相关产品推荐
相关产品推荐

