我在(自制的)基于C的python扩展中运行一些计算量很大的模拟。有时我会搞错东西,想终止模拟。但是,Ctrl-C似乎没有任何效果(除了在屏幕上打印^C
),所以我不得不使用kill
或系统监视器来终止进程。在
据我所见,python只是等待C扩展完成,而在这段时间内并没有真正与它通信。在
有没有办法让它成功?在
更新:主要答案(针对我的具体问题)是:
1重写代码以定期将控制权传递回调用者(下面回答Allowing Ctrl-C to interrupt a python C-extension),或者
2使用PyErr_CheckSignals()
(下面回答https://stackoverflow.com/a/33652496/423420)
我会重新设计C扩展,这样它们就不会运行很长时间。在
因此,将它们分成更基本的步骤(每个步骤运行很短的时间,例如10到50毫秒),然后用Python代码调用这些更基本的步骤。在
continuation passing style可能与理解有关,作为一种编程风格。。。在
^{} in the shell sends ^{} to the foreground process group 。} (这意味着:它不应该减慢速度),并在必要时运行Python信号处理程序,或者如果您的模拟允许Python代码执行(例如。,如果模拟使用Python回调)。如果扩展在后台线程中运行,那么释放GIL就足够了(允许Python代码在主线程中运行,从而使信号处理程序能够运行)。在
python
接收到信号时用C代码设置一个标志。如果您的C扩展在主线程中运行,那么不会运行任何Python信号处理程序(因此您不会在Ctrl-C
上看到KeyboardInterrupt
异常),除非您调用检查标志的^{相关:Cython, Python and KeybordInterrupt ingored
Python在
SIGINT
上安装了一个信号处理程序,它只是设置一个由主解释器循环检查的标志。要使这个处理程序正常工作,Python解释器必须运行Python代码。在您有几个可用的选项:
Py_BEGIN_ALLOW_THREADS
/Py_END_ALLOW_THREADS
来释放C扩展代码周围的GIL。不持有GIL时不能使用任何Python函数,但是Python代码(和其他C代码)可以与C线程并发运行(真正的多线程处理)。一个单独的Python线程可以在C扩展旁边执行并捕捉Ctrl+C信号。在SIGINT
处理程序并调用原始(Python)信号处理程序。然后,SIGINT
处理程序可以做任何它需要做的事情来取消C扩展代码并将控制权返回给Python解释器。在相关问题 更多 >
编程相关推荐