2 回答

TA貢獻1802條經驗 獲得超4個贊
您必須定期檢查未決信號,例如,在模擬循環(huán)的第N次迭代中:
from cpython.exc cimport PyErr_CheckSignals
cdef Run(self):
while True:
# do some work
PyErr_CheckSignals()
PyErr_CheckSignals將運行與信號模塊一起安裝的信號處理程序(KeyboardInterrupt必要時包括升高)。
PyErr_CheckSignals速度非???,可以經常調用它。請注意,應該從主線程調用它,因為Python在主線程中運行信號處理程序。從輔助線程調用它無效。
解釋
由于信號是在不可預測的時間異步傳遞的,因此直接從信號處理程序運行任何有意義的代碼是有問題的。因此,Python將傳入的信號排隊。該隊列稍后作為解釋器循環(huán)的一部分進行處理。
如果您的代碼已完全編譯,則解釋器循環(huán)將永遠不會執(zhí)行,并且Python沒有機會檢查和運行排隊的信號處理程序。

TA貢獻1844條經驗 獲得超8個贊
如果您嘗試處理KeyboardInterrupt釋放GIL的代碼(例如,因為它使用cython.parallel.prange),則需要重新獲取GIL才能調用PyErr_CheckSignals。以下代碼段(改編自上面的@ nikita-nemkin的答案)說明了您需要執(zhí)行的操作:
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()
添加回答
舉報