python - 如何为在 C++ 应用程序中使用嵌入 python 创建的新线程状态获取 GIL
问题描述
我有一个 C++ 应用程序,我们提供了一个 python 编辑器(使用 python 3.7),用户可以在编辑器中输入和执行 python 代码。以下是我们在执行用户提供的脚本之前创建新线程状态并使其成为当前状态的示例代码。
#include <python.h>
PyThreadState* globalthread;
void executescript()
{
PyEval_SaveThread();
PyThreadState* ts = PyThreadState_New(globalthread->interp);
int gilstate = PyGILState_Check(); //check whether GIL is with current thread or not
if (!gilstate)
{
PyEval_RestoreThread(ts);
}
else
{
PyThreadState_Swap(ts);
}
// get the thread state with which GIL is currently assigned
PyThreadState * gilthreadstate = PyGILState_GetThisThreadState();
//----> the above line return pointer to global thread state (gilthreadstate == globalthread)
//----> which means the GIL is not acquired by the new current thread
gilstate = PyGILState_Check(); //results in zero as GIL is not with current thread
std::string str = "def script():\n\timport sys\n\tsys.path.append('C:\\Python\\Python37\\Lib\\site-packages')\n\tprint(sys.path)\n\timport numpy\n\tarr = numpy.array([1, 2, 3, 4, 5])\n\tprint(arr)\nscript()";
PyRun_SimpleString(str.c_str());
PyThreadState_Clear(ts);
PyThreadState_DeleteCurrent();
PyEval_RestoreThread(globalthread);
//following stmt returns 1 as the current thread is global thread and it has GIL with it
gilstate = PyGILState_Check();
}
int main()
{
Py_Initialize();
PyEval_InitThreads();
globalthread = PyThreadState_Get();
executescript();
PyThreadState_Swap(globalthread);
Py_FinalizeEx();
return 0;
}
新的当前线程在调用 PyEval_RestoreThread 或 PyThreadState_Swap 时未获取 GIL。由于这个原因,Python 脚本已经import numpy
或将会以死锁告终。import pandas
有人可以让我知道如何获取新线程状态的 GIL 或代码错误的地方吗?
解决方案
hn-1-8e9-wheres-my-share-m 的评论通过创建一个新的 C++ 线程解决了这个问题。这是我修改后的代码。
#include <python.h>
#include <thread>
PyThreadState* globalthread;
void execute()
{
PyThreadState* ts = PyThreadState_New(globalthread->interp);
int gilstate = PyGILState_Check();
if (!gilstate)
{
PyEval_RestoreThread(ts);
}
else
{
PyThreadState_Swap(ts);
}
std::string str = "def script():\n\timport sys\n\tsys.path.append('C:\\Python\\Python37\\Lib\\site-packages')\n\tprint(sys.path)\n\timport numpy\n\tarr = numpy.array([1, 2, 3, 4, 5])\n\tprint(arr)\nscript()";
PyRun_SimpleString(str.c_str());
PyThreadState_Clear(ts);
PyThreadState_DeleteCurrent();
}
int main()
{
Py_Initialize();
globalthread = PyThreadState_Get();
PyEval_SaveThread();
std::thread t(executePythonScript);
t.join();
PyEval_RestoreThread(globalthread);
//PyThreadState_Swap(globalthread);
Py_FinalizeEx();
return 0;
}
感谢您指出帖子。
推荐阅读
- angular - Can't resolve all parameters for FormControl in my-project/node_modules/@angular/forms/forms.d.ts: (?, ?, ?)
- docker - 将文件夹从 Docker 复制到主机
- javascript - 如何通过他的索引将项目推送到 Obj Array
- php - Laravel:将 Where 子句添加到附加的自定义属性
- javascript - 不同 Autrelia Import 语句之间的区别
- flutter - 如何使颤动容器滚动?
- firebase - 来自客户端的firebase云函数调用将我重定向到accounts.google.com/ServiceLogin
- react-native - 过滤器功能不会在本机反应中重新调整任何内容
- azure - Azure 应用程序 oauth2 在客户端凭据授予类型中生成错误的访问令牌
- javascript - 如何使用 react-hook 复制基于类的组件异步 setState 方法