问题描述
我正在使用 C 嵌入 API 嵌入 Python。主线程做
Py_Initialize();
PyEval_InitThreads();
然后我有更多由本机代码创建的线程,它们的生命周期我无法控制。他们也需要调用 Python。到目前为止,他们似乎与
一起工作得很好void* gil = PyGILState_Ensure();
calls to Python go here
PyGILState_Release(gil);
问题在于这个简单的设置,我在使用 threading.local
的 Python 代码时遇到了问题。想象一下辅助线程 S
,它定期执行 increase_counter
:
// initialized once at the beginning of program to
// an instance of threading.local()
PyObject* threadLocal;
...
void increase_counter()
{
void* gil = PyGILState_Ensure();
// this really does C API calls,but for simplicity I'll write Python
if hasattr(threadLocal,"counter"):
threadLocal.counter += 1
else:
threadLocal.counter = 1
// end of Python
PyGILState_Release(gil);
}
嗯,问题是在线程 S
中多次调用 increase_counter
实际上并没有增加任何东西 - hasattr
总是返回 False
,而 {{ 的值一旦调用 counter
,该线程的 1}} 就会被丢弃。
只有在 PyGILState_Release
的整个主体都被包裹成以下内容时,它才能在 S
中正常工作:
S
针对这个问题我可以做的,但是在实际产品中void* gilForS = PyGILState_Ensure();
void* sPythonThreadState = PyEval_SaveThread();
// rest of the S body,that sometimes calls increase_counter
PyEval_RestoreThread(sPythonThreadState);
PyGILState_Release(gilForS);
的生命周期不是我控制的(它是一个线程池线程),只有S
,所以我不能让它在开始时运行 increase_counter
,我不能确保 PyEval_SaveThread
最终会被调用。
初始化像 PyEval_RestoreThread
这样的线程以便 S
在那里正常工作的正确方法是什么?
完整示例,按要求重现问题。打印两次“设置计数器”而不是“设置计数器”+“找到计数器!”。如果我取消注释 threading.local
中的代码,这在实际产品中无法执行,它会按预期工作:
async_thread
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)