15.8 C和Python中的线程混用¶

问题¶

你有一个程�需�混�使用C�Python和线程, 有些线程是在C中创建的,超出了Python解释器的控制范围。 并且一些线程还使用了Python C API中的函数。

解决方案¶

如果你想将C�Python和线程混�在一起,你需�确�正确的�始化和管�Python的全局解释器�(GIL)。 �想这样�,�以将下列代�放到你的C代�中并确�它在任何线程被创建之�被调用。

#include <Python.h>
  ...
  if (!PyEval_ThreadsInitialized()) {
    PyEval_InitThreads();
  }
  ...

对于任何调用Python对象或Python C API的C代�,确�你首先已�正确地获�和释放了GIL。 这�以用 PyGILState_Ensure() 和 PyGILState_Release() ��到,如下所示:

...
/* Make sure we own the GIL */
PyGILState_STATE state = PyGILState_Ensure();

/* Use functions in the interpreter */
...
/* Restore previous GIL state and return */
PyGILState_Release(state);
...

�次调用 PyGILState_Ensure() 都�相应的调用 PyGILState_Release() .

讨论¶

在涉�到C和Python的高级程�中,很多事情一起�是很常�的—— �能是对C�Python�C线程�Python线程的混�使用。 ��你确�解释器被正确的�始化,并且涉�到解释器的C代�执行了正确的GIL管�,应该没什么问题。

�注�的是调用 PyGILState_Ensure() 并�会立刻抢�或中断解释器。 如果有其他代�正在执行,这个函数被中断知�那个执行代�释放掉GIL。 在内部,解释器会执行周期性的线程切�,因此如果其他线程在执行, 调用者最终还是�以�行的(尽管�能�先等一会)。