多线程C语言中嵌入运行Python脚本
发布网友
发布时间:2024-10-23 11:28
我来回答
共1个回答
热心网友
时间:2024-11-03 02:16
本文阐述了在 C 语言的多线程环境中如何嵌入并运行 Python 脚本的实现方法。
产生这一需求的具体场景:
Initialization, Finalization, and Threads — Python 3.12.2 documentation
Python 线程安全
Python 代码通常通过 Python 解释器执行,但解释器本身并不具备线程安全性。为此,Python 提供了全局解释器锁(GIL),以确保同一时间只有一个线程可以操作 Python 对象或调用 Python/C API 函数。GIL 在进行 I/O 阻塞操作时会释放,以允许其他线程运行。
Python 解释器使用 PyThreadState 数据结构来存储线程相关数据,并通过全局变量保存当前线程的 PyThreadState 指针,可通过 PyThreadState_Get 接口获取。
一些多线程 Python 代码的内部处理机制:
具体到实际代码如下:
从这里可以看出,全局解释器锁用于保护指向线程状态数据的全局变量。
非 Python 创建的线程
当使用专用 Python API(如 threading 库)创建线程时,上述动作(持有或释放 GIL、存储或恢复线程状态指针)由库自动执行。当使用 C 语言创建线程时,默认情况下线程不持有 GIL,也没有线程状态结构。若需从这些线程中调用 Python 代码,需执行以下动作:
请注意,PyGILState* 函数假设只有一个全局解释器(由 Py_Initialize() 自动创建)。Python 支持创建额外的解释器(使用 Py_NewInterpreter()),但不能混合使用多个解释器与 PyGILState* API。
实现原理
C 语言的多线程中调用 Python C/API 接口执行 Python 脚本的方式有以下两种:
在下面的内容中,我们使用第 2 种方法,创建一个全局 Python 解释器以供所有线程使用。
代码
下面是实现的 C 语言代码:
下面是 Python 脚本代码:
下面是运行结果:
从运行结果中可以看出线程在不断轮换调用 Python 脚本,对变量进行增减操作。
Q&A 多 Python 环境选择问题
问题描述:在运行环境中,可能已存在其他版本的 Python 环境,且与 C 语言代码引用的 libpython 版本不匹配,从而引发 Python 版本兼容问题。
解决方法:在对 Python 进行初始化之前,先设置 Python 模块查找路径,使用以下接口:
实现代码:
错误日志输出
问题描述:在调用 Python C/API 时,错误信息通常使用 PyErr_Print() 直接打印,但在实际应用场景中,通常需要将错误日志输出到日志中。
解决方法:通过接口 PyObject *PyErr_Occurred() 检测 Python C/API 调用是否出错,若出错,则获取错误信息。
实现代码: