Я хочу иметь возможность прерывать длинную функцию с помощью Cython, используя обычную команду прерывания CTRL + C.
Моя длинная функция C ++ неоднократно вызывается в цикле while из кода Cython, но я хочу иметь возможность во время цикла отправлять «прерывание» и блокировать цикл while.
Прерывание также должно ждать завершения функции longFunction (), чтобы никакие данные не были потеряны или оставались в неизвестном состоянии.
Это одна из моих первых реализаций, которая, очевидно, не работает:
computed=0;
print "Computing long function..."while ( computed==0 ):
try:
computed = self.thisptr.aLongFunction()
except (KeyboardInterrupt, SystemExit):
computed=1
print '\n! Received keyboard interrupt.\n'
break;
(P.S. self.thisptr
указатель на текущий класс, который реализует aLongFunction()
)
Вы должны быть в состоянии сделать что-то вроде этого:
import signal
class Test():
def __init__(self):
self.loop_finished = False
signal.signal(signal.SIGINT, self.abort_loop)
def abort_loop(self, signal, frame):
self.loop_finished = True
def go(self):
while not self.loop_finished:
print "Calculating"
# Do your calculations
# Once calcations are done, set self.loop_finished to True
print "Calculating over"
Test().go()
Вы также можете использовать дополнительные переменные, чтобы отслеживать, было ли вычисление прервано вручную или нет.
Я не мастер Python C-Api foo, однако это работает, но, возможно, это не лучший способ:
cdef extern from "Python.h":
int PyErr_CheckSignals()
def test_interrupt():
cdef int i = 0
while i < 9999999999 and not PyErr_CheckSignals():
# do fancy stuff.
i += 1
Конечно, это не асинхронно, что возможно, но я не знаю, и это прерывает цикл для любого сигнала, а не только Ctrl + C. Также, возможно, лучше не проверять сигналы на каждой итерации цикла, по крайней мере, если то, что делается, очень дешево.
Вы могли бы позвонить PyErr_Occurred
и т.д., если PyErr_CheckSignals
не вернулся 0
и посмотрим, что за Exception
был поднят, чтобы пойти специально для KeybordInterrupt
или определенные сигналы убийства. (Во всяком случае, проверьте Python C-Api для деталей там …)
Если вы звоните на Cython cdef
Функция внутри цикла while вы можете достичь этого, даже если вы добавите except *
:
cdef function(...) except *:
pass
смотрите также http://docs.cython.org/src/userguide/language_basics.html#error-return-values