多线程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 调用是否出错,若出错,则获取错误信息。

实现代码:
声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。
E-MAIL:11247931@qq.com