C呼叫Python之多執行緒與traceback列印
阿新 • • 發佈:2021-01-22
技術標籤:Python
一、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、參考
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; }