Python如何在Windows下处理Ctrl-C

Python如何在Windows下处理Ctrl-C,python,windows,signals,Python,Windows,Signals,实际上,有两个问题。然而,我认为他们是密切相关的,所以我一起问他们。我在Windows下使用Python 2.7.10 32位 第一个是关于这个项目的: import sys sys.stdin.readline() a = 1 b = 2 print 'hello' import sys while True: sys.stdin.readline() 当程序要求输入时,如果我按Ctrl-C,程序将被键盘中断停止。但是,此异常将发生在打印“hello”中,而不是在sys.std

实际上,有两个问题。然而,我认为他们是密切相关的,所以我一起问他们。我在Windows下使用Python 2.7.10 32位

第一个是关于这个项目的:

import sys

sys.stdin.readline()
a = 1
b = 2
print 'hello'
import sys

while True:
    sys.stdin.readline()
当程序要求输入时,如果我按Ctrl-C,程序将被键盘中断停止。但是,此异常将发生在
打印“hello”
中,而不是在
sys.stdin.readline()中

第二个是关于这个节目:

import sys

sys.stdin.readline()
a = 1
b = 2
print 'hello'
import sys

while True:
    sys.stdin.readline()
当我想停止这个程序时,我必须先按Ctrl-C,然后按Enter或再次按Ctrl-C


这两个问题都不是在Linux下发生的,而且在调试时很烦人。如果有人能给我一个详细的解释,我将不胜感激。

您可能想检查Win 7+中的SIGINT(
ctrl+c
),一个ctrl+c事件在conhost.exe中启动,并跳转到csrss.exe,它在您的进程中创建一个远程线程,从kernel32.dll中的
CtrlRoutine
开始。这将调用已注册的控件事件处理程序。进程中的每个C运行时都有一个调用其注册的
SIGINT
函数的控制处理程序,该函数将被设置为Python使用的CRT中的Python处理程序。此调用发生在一个新线程上,因此Python的本机处理程序只为主线程设置一个标志,稍后将调用已注册的Python处理程序,例如引发
KeyboardInterrupt
的函数。Linux在内核中本机实现信号。因此,底层的
read()
系统调用被中断,Python的本机信号处理程序在主线程上执行。然后,当
readline
实现恢复时,
getc
返回
EOF
并设置
stdin
流错误状态,
errno
设置为
EINTR
。鉴于此,Python知道检查其信号标志,并将调用已注册的
SIGINT
处理程序,例如引发
KeyboardInterrupt
的默认处理程序。这一切都很顺利,因为POSIX系统是为信号设计的,而它们在Windows上是非本机的。请注意,Windows控制台I/O是罕见的同步系统调用会被中断的情况,因此,C运行时在其低级的
read
write
函数中没有将
errno
设置为
EINTR
。在这种情况下,它可以通过检查
错误\u操作\u中止
。Python的I/O实现也不检查这一点,除了在REPL和内置的
raw\u input
input
(即
PyOS\u StdioReadline
)中用于读取输入的代码中。Python 3使用Windows事件对象来帮助在这种竞争条件下进行同步,但仍有改进的余地。我在Windows 8+中提到了上述更改,因为它在
ReadFile
WriteFile
中引入了一个bug。当操作中断时,他们不再设置
错误\u操作\u中止
。现在Python的
PyOS\u StdioReadline
无法区分文件结尾(
EOF
)和Windows 8+中的中断读取。因此,Ctrl+C使REPL退出,就像您输入了Ctrl+Z.和
raw_input
input
set
eoferor
,这与检查由Ctrl+C线程设置的
SIGINT
标志相匹配。解决方法包括完全重写以使用
ReadConsole
API。