2 回答

TA贡献1802条经验 获得超4个赞
您必须定期检查未决信号,例如,在模拟循环的第N次迭代中:
from cpython.exc cimport PyErr_CheckSignals
cdef Run(self):
while True:
# do some work
PyErr_CheckSignals()
PyErr_CheckSignals将运行与信号模块一起安装的信号处理程序(KeyboardInterrupt必要时包括升高)。
PyErr_CheckSignals速度非常快,可以经常调用它。请注意,应该从主线程调用它,因为Python在主线程中运行信号处理程序。从辅助线程调用它无效。
解释
由于信号是在不可预测的时间异步传递的,因此直接从信号处理程序运行任何有意义的代码是有问题的。因此,Python将传入的信号排队。该队列稍后作为解释器循环的一部分进行处理。
如果您的代码已完全编译,则解释器循环将永远不会执行,并且Python没有机会检查和运行排队的信号处理程序。

TA贡献1844条经验 获得超8个赞
如果您尝试处理KeyboardInterrupt释放GIL的代码(例如,因为它使用cython.parallel.prange),则需要重新获取GIL才能调用PyErr_CheckSignals。以下代码段(改编自上面的@ nikita-nemkin的答案)说明了您需要执行的操作:
from cpython.exc cimport PyErr_CheckSignals
from cython.parallel import prange
cdef Run(self) nogil:
with nogil:
for i in prange(1000000)
# do some work but check for signals every once in a while
if i % 10000 == 0:
with gil:
PyErr_CheckSignals()
添加回答
举报