gpt4 book ai didi

python - 如何使用 Py_AddPendingCall

转载 作者:太空狗 更新时间:2023-10-30 01:09:31 24 4
gpt4 key购买 nike

我有一个在 C 线程中运行的嵌入式 Python 程序。

当 Python 解释器切换线程上下文(将控制权交给另一个线程)时,我希望得到通知,以便我可以执行某些必要的操作。

似乎Py_AddPendingCall正是我要找的。但是,API 文档对此函数的介绍非常简短,我对应该如何使用 Py_AddPendingCall 感到困惑。通过阅读文档,我的理解是:

  • 工作线程调用 Py_AddPendingCall 并分配一个处理程序功能。
  • 当 Python 解释器运行时,它调用处理函数每当它把控制权让给另一个线程时
  • 处理程序本身在 main 解释器线程中执行,与GIL获得

我在谷歌上搜索了显示如何使用 Py_AddPendingCall 的示例代码,但我找不到任何东西。我自己尝试使用它根本行不通。处理程序从未被调用。

我的工作线程代码:

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>

const char* PYTHON_CODE =
"while True:\n"
" for i in range(0,10): print(i)\n"
"\n";

int handler(void* arg)
{
printf("Pending Call invoked!\n");
abort();
}

void* worker_thread(void*)
{
PyGILState_STATE state = PyGILState_Ensure();
int res = Py_AddPendingCall(&func, nullptr);
cout << "Result: " << res << endl;
PyRun_SimpleString(CODE);
PyGILState_Release(state);

return 0;
}

int main()
{
Py_Initialize();
PyEval_InitThreads();
PyEval_ReleaseLock();

pthread_t threads[4];
for (int i = 0; i < 4; ++i)
pthread_create(&threads[i], 0, worker_thread, 0);

for (int i = 0; i < 4; ++i) pthread_join(threads[i], 0);

Py_Finalize();
}

在此示例中,worker_thread 在 C 中作为 pthread 工作线程被调用。在此测试中,我运行了 4 个工作线程,因此应该会发生一些上下文切换。这将无限循环,但永远不会调用挂起的调用处理程序。

那么,有人可以提供一个最小的工作示例来说明应该如何使用 Py_AddPendingCall 吗?

最佳答案

挂起的调用只在主线程上执行,主线程在执行Python代码时只能为挂起的调用服务。因此,主线程必须运行一个解释器循环才能为任何挂起的调用提供服务。来自 Python/ceval.c:

Py_MakePendingCalls(void)
{
...

/* only service pending calls on main thread */
if (main_thread && PyThread_get_thread_ident() != main_thread)
return 0;

...
}

在嵌入场景中,“主线程”是调用 PyEval_InitThreads 的线程(请注意,它也会在您第一次从 Python 代码启动线程时自动调用)。由于您的主线程位于 pthread_join 中,因此它不执行 Python 代码,因此不分派(dispatch)挂起的调用。

另请注意,处理程序仅在控制权交给主线程时执行——如果控制权从一个工作线程转到另一个工作线程,则处理程序不会运行。因此,Py_MakePendingCalls 可能不是用于此任务的合适接口(interface)。

关于python - 如何使用 Py_AddPendingCall,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12448737/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com