使用CPython API在C++线程中调用Python代码时线程异常终止问题
问题描述
我在C++项目中使用CPython API调用Python代码,原本单线程下的runPython函数(代码如下)以无限循环方式调用Python代码一切正常,无内存泄漏且可长期运行。
void runPython(){ // init python module // load module // load function while(1){ // create list using c-python api // populate input // call python function using c-python APIs // get output and free up the references } }
但将该函数放入std::thread或pthread中执行时,Python代码执行到中途线程便异常终止,不再返回runPython函数,其他并行线程运行正常。尝试增大pthread栈至1000MB仍未解决问题。请问可能的原因是什么?(注:传入Python函数的是7-8个大小为100000的float32类型大列表)
可能的原因分析
- GIL管理缺失:CPython的全局解释器锁(GIL)要求每个执行Python代码的线程必须先获取GIL。单线程下无需手动处理,但子线程中如果没有调用
PyGILState_Ensure()获取锁,或操作完成后未用PyGILState_Release()释放锁,会直接导致Python运行时异常,引发线程终止。 - 线程状态未初始化:CPython的API并非完全线程安全,每个线程调用Python接口前需要单独初始化线程状态。如果主线程未提前调用
PyEval_InitThreads(),或子线程未通过PyThreadState_New()/PyThreadState_Swap()设置专属线程状态,会触发运行时错误。 - 大对象操作的线程安全问题:虽然增大了线程栈,但Python列表对象在堆上分配,栈大小不影响。若子线程未持有GIL时创建或操作这些大列表,会触发内存访问冲突,导致线程崩溃。
- Python异常未捕获:Python函数内部若抛出未捕获的异常,多线程环境下CPython API不会返回错误状态,而是直接终止当前线程。需要在调用Python函数后通过
PyErr_Occurred()检查异常并处理,避免线程直接退出。 - CPython版本兼容性bug:部分旧版本CPython在多线程调用API时存在线程状态管理的bug,建议切换到3.8及以上的稳定版本测试是否解决问题。
内容的提问来源于stack exchange,提问作者ABD
相关产品推荐
相关产品推荐

