允许Ctrl-C中断python C扩展

问题描述:

我在(自制的)基于C的python扩展中运行一些计算量大的模拟。偶尔我得到错误的东西,并想终止模拟。但是,Ctrl-C似乎没有任何效果(除了在屏幕上打印^C,所以我必须使用kill或系统监视器来终止进程。允许Ctrl-C中断python C扩展

据我所见,python只是等待C扩展到结束,并没有真正在此期间与它通信。

有没有一种方法,使这项工作?

+0

见http://*.com/questions/1112343/how-do-i-capture-sigint-in-python – user1929959

+0

相关:[CTRL + C不会中断调用共享 - 在Python中使用CTYPES的图书馆](http://*.com/q/14271697/4279) – jfs

我会重新设计的C扩展,使他们不会长时间运行

因此,将它们分成更基本的步骤(每个步骤都运行一段很短的时间,例如10到50毫秒),并有Python代码调用这些更基本的步骤。

continuation passing style可能是相关的理解,作为一种编程风格。

+3

对不起,在这种情况下根本不是一个选项:) 这是一个具有大量步骤的模拟和速度是至关重要的。在每一步(甚至是定期)与python进行接口会损害效率。 –

+0

尝试将步骤聚合成持续几毫秒的事物。然后去Python的开销可以忽略不计...... –

+0

这当然值得思考,但它确实引发了很多与内存管理等问题。谢谢! –

Python有安装在SIGINT信号处理程序简单地设置由主解释器检查的标志。为了使这个处理程序正常工作,Python解释器必须运行Python代码。

你必须给你几个选项:

  1. 使用Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS释放GIL在你的C扩展代码。不保留GIL时不能使用任何Python函数,但Python代码(和其他C代码)可能与C线程(真正的多线程)同时运行。一个单独的Python线程可以与C扩展一起执行并捕获Ctrl + C信号。
  2. 设置您自己的SIGINT处理程序并调用原始(Python)信号处理程序。然后,您的SIGINT处理程序可以执行任何需要的操作来取消C扩展代码并将控制返回给Python解释器。
+0

(1)[释放GIL只会在C后缀运行在后台线程时才会有所作为](http://*.com/q/14271697/4279)。 (2)[调用'Py_Err_CheckSignals()'而不是手动调用Python信号处理程序](http://*.com/a/33652496/4279) – jfs

然而,按Ctrl-C似乎没有任何效果

Ctrl-C in the shell sends SIGINT to the foreground process grouppython收到信号后在C代码中设置一个标志。如果您的C扩展在主线程中运行,那么将不会运行Python信号处理程序(因此Ctrl-C上将不会出现KeyboardInterrupt例外),除非您调用PyErr_CheckSignals()来检查标志(意思是说:它不会减慢速度)并在必要时运行Python信号处理程序,或者如果您的模拟允许Python代码执行(例如,如果模拟使用Python回调)。如果扩展在后台线程中运行,那么它就足以释放GIL(允许Python代码在主线程中运行,使信号处理程序能够运行)。

相关:Cython, Python and KeybordInterrupt ingored