1. 程式人生 > 其它 >C呼叫Python之多執行緒與traceback列印

C呼叫Python之多執行緒與traceback列印

技術標籤:Python

一、C多執行緒呼叫Python

1、參考如下文章:

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