15.7 从C扩展ä¸é‡Šæ”¾å…¨å±€é”�¶
问题¶
ä½ æƒ³è®©C扩展代ç �å’ŒPython解释器ä¸çš„其他进程一起æ£ç¡®çš„æ‰§è¡Œï¼Œ é‚£ä¹ˆä½ å°±éœ€è¦�去释放并é‡�新获å�–全局解释器é”�(GIL)。
解决方案¶
在C扩展代ç �ä¸ï¼ŒGILå�¯ä»¥é€šè¿‡åœ¨ä»£ç �䏿�’入下é�¢è¿™æ ·çš„å®�æ�¥é‡Šæ”¾å’Œé‡�新获å�–:
#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args) {
...
Py_BEGIN_ALLOW_THREADS
// Threaded C code. Must not use Python API functions
...
Py_END_ALLOW_THREADS
...
return result;
}
讨论¶
å�ªæœ‰å½“ä½ ç¡®ä¿�没有Python C API函数在C䏿‰§è¡Œçš„æ—¶å€™ä½ æ‰�能安全的释放GIL。 GIL需è¦�被释放的常è§�的场景是在计算密集型代ç �ä¸éœ€è¦�在C数组上执行计算(比如在numpyä¸ï¼‰ 或者是è¦�执行阻塞的I/Oæ“�作时(比如在一个文件æ��述符上读å�–或写入时)。
当GIL被释放å�Žï¼Œå…¶ä»–Python线程æ‰�被å…�è®¸åœ¨è§£é‡Šå™¨ä¸æ‰§è¡Œã€‚
Py_END_ALLOW_THREADS �会阻塞执行直到调用线程�新获�了GIL。