简体   繁体   English

在Cython中用键盘中断`while循环`

[英]Interrupting `while loop` with keyboard in Cython

I want to be able to interrupt a long function with cython, using the usual CTRL+C interrupt command. 我希望能够使用通常的CTRL + C中断命令使用cython中断长函数。 My C++ long function is repeatedly called inside a while loop from Cython code, but I want to be able, during the loop, to send an "interrupt" and block the while loop. 我的C ++ long函数在Cython代码的while循环中重复调用,但我希望能够在循环期间发送“中断”并阻止while循环。

The interrupt also should wait the longFunction() to finish, so that no data are lost or kept in unknown status. 中断也应该等待longFunction()完​​成,这样就不会丢失数据或保持未知状态。

This is one of my first implementation, which obviously doesn't work: 这是我的第一个实现之一,显然不起作用:

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;

(ps self.thisptr is the pointer to the current class which implements aLongFunction() ) (ps self.thisptr是指向实现aLongFunction()的当前类的指针)

You should be able to do something like this: 你应该可以做这样的事情:

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

You can also use additional variables to keep track of whether the computation was manually aborted or not. 您还可以使用其他变量来跟踪计算是否手动中止。

I am not a Python C-Api foo master, however this works, but maybe its not the best way: 我不是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

Of course that is not asynchronous which is maybe possible but I do not know and this breaks the loop for any signal, not just Ctrl+C. 当然这不是异步,这可能是可能的,但我不知道,这打破了任何信号的循环,而不仅仅是Ctrl + C. Also maybe its better to not check signals every loop iteration, at least if what is done is very cheap. 也许最好不要在每次循环迭代中检查信号,至少如果做的是非常便宜的话。

You could call PyErr_Occurred , etc. if PyErr_CheckSignals did not return 0 and see what kind of Exception got raised to go specifically for KeybordInterrupt or certain kill signals. 你可以调用PyErr_Occurred等,如果PyErr_CheckSignals没有返回0 ,看看有什么样的Exception被提出专门用于KeybordInterrupt或某些kill信号。 (Anyway, check the python C-Api for details there...) (无论如何,检查python C-Api的详细信息......)


If you are calling a cython cdef function inside the while loop you may be able to achieve this also if you add except * : 如果你在while循环中调用cython cdef函数,你可能也可以实现这个,如果你添加except *

cdef function(...) except *:
    pass

see also http://docs.cython.org/src/userguide/language_basics.html#error-return-values 另见http://docs.cython.org/src/userguide/language_basics.html#error-return-values

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM