Windows:Jupyter 如何引发键盘中断?

Posted

技术标签:

【中文标题】Windows:Jupyter 如何引发键盘中断?【英文标题】:Windows: How does Jupyter throw a keyboard interrupt? 【发布时间】:2019-01-15 19:41:30 【问题描述】:

我知道如何中断内核(例如通过点击I 两次或通过在 Web 界面上中断内核)。但是,我为 Python(我使用的是 Windows)构建了一个 C 扩展,它在我的 C++ 代码(一个玩具示例)中处理 CTRL-C 事件:

static int s_interrupted = 0;

BOOL WINAPI consoleHandler(DWORD fdwCtrlType) 

  switch (fdwCtrlType)
  
  // Handle the CTRL-C signal.
  case CTRL_C_EVENT:
      s_interrupted = 1;
      return TRUE;
  


int main() 
    s_interrupted = 0;
    int output = 1;
    if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) 
        std::cout<<"ERROR: Could not set control handler"<<std::endl;
     else 
        std::cout<<"Control hanlder installed"<<std::endl;
    
    int k = 10000;
    while (int i < k) 
        if (s_interrupted == 1) 
            output = -1;
            break;
        
         output = i
         i = i + 1;
    
    return output;

我的主程序的输出根据s_interrupted 的值而变化。换句话说,如果我不按 CTRL+C,程序将完成 while 循环并返回一个整数。如果我按 CTRL+C,while 循环将终止并返回一个不同的整数。我不希望在我的 Python 终端中看到 KeyboardInterrupt

当我在终端中调用这个 C 扩展时,它工作正常。但是,当我在 Jupyter 笔记本中执行此操作时,程序的行为就像我从未中断过内核一样。当我中断内核时,Jupyter 不会发送SIGINT 吗?

【问题讨论】:

你读过Jupyter messaging documentation吗?重新启动内核只是前端到后端的另一条消息。 【参考方案1】:

您的代码没有安装信号处理程序并且没有使用s_signal_handler。您需要调用signal 函数来注册您的回调。

#include <atomic>
#include <signal.h>

::std::atomic<bool> s_interrupted;

static void signal_handler(int signal)

  s_interrupted = true;


int main()

    ::signal(SIGINT, &::signal_handler);

【讨论】:

抱歉,我更新了我的代码。 s_signal_handler 在这里不需要。我已经有consoleHandler::signal() 是做什么的? @user1691278 signal 函数注册信号处理程序,因此您可以实际处理SIGINT SetConsoleCtrlHandler 不做这项工作吗? @user1691278 有点像,但它是 Windows 特定的东西,信号处理程序更便携。而且CTRL+CSIGINT不完全一样 那么CTRL+C 是什么?【参考方案2】:

你不能在这里使用consoleHandler(),因为没有控制台。 IPython 内核是一个“无头”子进程,它根据请求执行代码,由 Jupyter 前端引导。

为了中断正在运行的 IPython 内核,Jupyter 前端使用SIGINT 信号。它在 POSIX 和 Windows 上都这样做;在 Windows 上,Jupyter 使用围绕 CreateEventASetEventWaitForMultipleObjects 构建的额外基础架构来实现与 POSIX os.killpg(PID, SIGINT) 调用相同的结果;一个单独的线程轮询事件并在主线程中触发SIGINT 信号。

请注意,IPython 内核显式地为它处理的每条消息恢复 Python 默认信号处理程序。见ipykernel.kernelbase.Kernel implementations for the pre_ and post_handler_hook methods:

 self.saved_sigint_handler = signal(SIGINT, default_int_handler)

 signal(SIGINT, self.saved_sigint_handler)

这两个钩子在每个消息处理程序之前和之后执行(对于every message sent by the frontend to the kernel process,包括execute messages)。

在 Python 主线程中引发 KeyboardInterrupt 的是 signal.default_int_handler。如果您的代码必须检测中断,则每次 IPython 执行一个单元格时,它都需要注册自己的 signal 处理程序。

附带说明:独立的交互式 Python 解释器不使用 SetConsoleCtrlHandler 来检测键盘中断或者; Python 源代码中唯一使用的地方是py launcher,然后才使用返回TRUE 的处理程序使控制代码静音。相反,Python 依赖于Windows sending the SIGINT signal to all attached console processes for the active console window。

【讨论】:

以上是关于Windows:Jupyter 如何引发键盘中断?的主要内容,如果未能解决你的问题,请参考以下文章

汇编语言-使用BIOS进行键盘输入和磁盘读写

汇编语言-18使用BIOS进行键盘输入和磁盘读写

第17章 使用BIOS进行键盘输入和磁盘读写

第17章 使用BIOS进行键盘输入和磁盘读写

计算机键盘上有break键吗?有啥作用?在啥位置?如果没有那中断键是哪个键子!

Atom / Sublime喜欢Jupyter中的Multiple选择