-
初始化和终止 Python 解释器:
在使用任何 Python API 之前,必须初始化 Python 解释器。- 确保
Py_Initialize
和Py_Finalize
只调用一次,通常在程序的生命周期内。 - 可以使用静态变量或单例模式来管理 Python 解释器的初始化和终止。
if(!Py_IsInitialized()) // 判断 Python 解释器是否已经初始化 { Py_Initialize(); // 初始化 Python 解释器 } // ... 进行 Python 对象的操作 ... Py_Finalize(); // 结束程序时再终止 Python 解释器
- 确保
-
全局解释器锁(GIL):
如果在多线程环境中使用 Python 解释器,需要确保线程安全。可以使用PyGILState_Ensure
和PyGILState_Release
来管理全局解释器锁(GIL)。PyGILState_STATE gstate; gstate = PyGILState_Ensure(); // 获取 GIL // ... 进行 Python 对象的操作 ... PyGILState_Release(gstate); // 释放 GIL
PyGILState_STATE
用起来各种问题,不如使用互斥锁。static QMutex mutex; QMutexLocker locker(&mutex); // ... 进行 Python 对象的操作 ...
暂时记录(有时间再来研究):
- 在
QRunnable
和QThreadPool
中使用PyGILState_Ensure
会导致死锁。 - 换成
QThread
能解决死锁问题,但是获取GIL后面的代码都没有再执行,当结束程序时会报:
或者QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
要么直接关闭程序,控制台Fatal Python error: PyEval_SaveThread: NULL tstate Python runtime state: initialized
return 1
。 - 调用 Python 封装成了单例类,关系应该不大。
可以参考:
链接: C++ 多线程调用Python脚本
链接: 记QT混编c++多次调用python脚本所出现的问题
链接: qt(c++)线程中调用python - 在
总结:
- 使用单例模式管理 Python 解释器的初始化和终止,确保只调用一次。
- 在执行 Python 代码时使用
QMutexLocker
进行互斥锁管理,确保线程安全。 - 在获取 GIL 后添加错误处理机制,确保在出现异常时能够正确释放 GIL。
- 使用
QThread
来管理线程,避免在QRunnable
和QThreadPool
中使用PyGILState_Ensure
导致的死锁问题。