C调用Python模块时PyImport_ImportModule二次调用崩溃求助
问题分析与解决方案
核心问题原因
- 重复初始化/终结Python导致扩展状态异常:你每次调用
run_python()都执行Py_Initialize()和Py_Finalize(),但requests这类依赖底层网络C扩展的模块,在Py_Finalize()后无法完全重置全局状态,二次初始化时会触发崩溃——这也是无网络时正常(未触发完整扩展逻辑)、有网络时崩溃的直接原因。 - 内存管理错误:
PyUnicode_AsUTF8()返回的指针指向Python对象管理的内存,在你调用Py_DecRef(resultPy)和Py_Finalize()后,该内存已被释放,返回的指针属于野指针,会引发未定义行为。
修复方案
关键修改思路
- 全局仅初始化一次Python,程序退出时再终结,避免重复初始化导致的扩展状态问题。
- 将Python返回的字符串复制到C自主管理的内存中,避免依赖Python对象的生命周期。
- 完善错误检查逻辑,避免空指针访问。
修复后的C代码
#include <stdio.h> #include <Python.h> #include <string.h> #include <stdlib.h> // 全局初始化Python,仅执行一次 void init_python_env() { Py_Initialize(); // 可选:重定向stderr到stdout,方便调试 PyRun_SimpleString("import sys\nsys.stderr = sys.stdout\n"); } // 全局清理Python环境,程序退出时执行 void cleanup_python_env() { Py_Finalize(); } const char* fetch_currency() { // 导入Python模块 PyObject* pModule = PyImport_ImportModule("geo"); if (!pModule) { PyErr_Print(); return strdup("EUR"); } // 获取目标函数 PyObject* get_currency_func = PyObject_GetAttrString(pModule, "get_currency"); if (!get_currency_func || !PyCallable_Check(get_currency_func)) { PyErr_Print(); Py_DecRef(pModule); return strdup("EUR"); } // 调用函数获取结果 PyObject* currency_obj = PyObject_CallObject(get_currency_func, NULL); if (!currency_obj) { PyErr_Print(); Py_DecRef(get_currency_func); Py_DecRef(pModule); return strdup("EUR"); } // 将Python字符串复制到C堆内存,脱离Python内存管理 const char* raw_str = PyUnicode_AsUTF8(currency_obj); char* result = strdup(raw_str ? raw_str : "EUR"); // 清理Python对象引用 Py_DecRef(currency_obj); Py_DecRef(get_currency_func); Py_DecRef(pModule); return result; } int main() { init_python_env(); // 第一次调用 const char* curr1 = fetch_currency(); printf("First currency: %s\n", curr1); free((void*)curr1); // 释放自主管理的内存 // 第二次调用 const char* curr2 = fetch_currency(); printf("Second currency: %s\n", curr2); free((void*)curr2); cleanup_python_env(); return 0; }
补充注意事项
- 确保
geo.py位于程序运行的工作目录,或通过sys.path.append()添加模块所在路径。 - 若因特殊需求必须多次初始化/终结Python(不推荐),需确认所有依赖的第三方模块都支持重复初始化,目前
requests等网络模块无法保证这一点。 - 编译命令保持原配置即可,确保链接正确的Python库版本。
内容的提问来源于stack exchange,提问作者il.giaco
相关产品推荐
相关产品推荐

