0
点赞
收藏
分享

微信扫一扫

C调用Python之多线程与traceback打印


一、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;
}

 

 

举报

相关推荐

0 条评论