Прерывание `while loop` с клавиатуры в Cython

Я хочу иметь возможность прерывать длинную функцию с помощью 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() )

3

Решение

Вы должны быть в состоянии сделать что-то вроде этого:

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()

Вы также можете использовать дополнительные переменные, чтобы отслеживать, было ли вычисление прервано вручную или нет.

0

Другие решения

Я не мастер 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

0

По вопросам рекламы [email protected]