一、C多线程调用Python
1、参考如下文章:
- python中的GIL详解
- Python进阶:深入GIL(上篇)
- Python进阶:深入GIL(下篇)
- c程序多次调用python脚本的正确打开模式
- C++多线程中调用python api函数
- C语言多线程调用python
- 【Python笔记1.1】C/C++多线程调Python
- C++调用PythonAPI线程状态和全局解释器锁
- Python/C API 参考手册
2、示例代码
主线程中这样处理
// 初始化
Py_Initialize();
if ( !Py_IsInitialized() )
return
// 初始化线程支持
PyEval_InitThreads();
// 启动子线程前执行,为了释放PyEval_InitThreads获得的全局锁,否则子线程可能无法获取到全局锁。
PyEval_ReleaseThread(PyThreadState_Get());
// 其他的处理,如启动子线程等
......
// 保证子线程调用都结束后
PyGILState_Ensure();
Py_Finalize();
// 之后不能再调用任何python的API
在主线程,或者子线程中,调用python本身函数采用如下处理
PyGILState_STATE state;
state = PyGILState_Ensure();
...
// 调用python的API函数处理
...
PyGILState_Release(state);
二、打印traceback信息
1、参考
- c++ 如何获取Python异常文本
- Python学习:使用boost c++嵌入python,获取异常信息输出到字符串
- C++中处理PYTHON的异常
2、示例代码
std::string getPythonErrorInfo(void) {
string errorMsg = "";
PyObject *pType, *pValue, *pTraceback;
PyErr_Fetch(&pType, &pValue, &pTraceback);
if (pValue == nullptr) {
return errorMsg;
}
if (pTraceback == nullptr) {
errorMsg += PyUnicode_AsUTF8(pValue);
} else {
PyErr_NormalizeException(&pType, &pValue, &pTraceback);
PyObject *pTraceModule = PyImport_ImportModule("traceback");
if (pTraceModule != nullptr) {
PyObject *pModuleDict = PyModule_GetDict(pTraceModule);
if (pModuleDict != nullptr) {
PyObject *pFunc = PyDict_GetItemString(pModuleDict, "format_exception");
if (pFunc != nullptr) {
PyObject *errList = PyObject_CallFunctionObjArgs(pFunc, pType, pValue,
pTraceback, nullptr, nullptr);
if (errList != nullptr) {
int listSize = PyList_Size(errList);
for (int i = 0; i < listSize; ++i) {
auto item = PyList_GetItem(errList, i);
errorMsg += PyUnicode_AsUTF8(item);
}
Py_XDECREF(errList);
}
Py_XDECREF(pFunc);
}
Py_XDECREF(pModuleDict);
}
Py_XDECREF(pTraceModule);
}
}
Py_XDECREF(pType);
Py_XDECREF(pValue);
Py_XDECREF(pTraceback);
return errorMsg;
}