Windows Python 解释器在 Ctrl+C 时退出
Windows Python interpreter exits on Ctrl+C
对于我使用过的大多数 Python 解释器,Ctrl+C 将使解释器打印出“KeyboardInterrupt
”并保持打开状态。但是,最近在新计算机上安装时,Ctrl+C 导致解释器退出,这是不可取的。
- 设置
signal.SIGINT
处理程序仍然存在。
- 没有 运行 可以调整行为的启动脚本。
raise KeyboardInterrupt
不退出解释器。
- Ctrl+C 没有发出任何文本。在 Ctrl+Break 时,
^C
在退出前发出。
如果我在以下代码段的暂停期间按 Ctrl+C,解释器将保持打开状态。
import time
try:
time.sleep(100)
except KeyboardInterrupt:
pass
环境:Python 3.4.3 on Windows 10
当 Windows 8 及更高版本上 运行 时,shell 3.6 之前的 Python 版本的 Ctrl+C 处理被破坏。 input
和 raw_input
也被破坏了,你会得到 EOFError
而不是 KeyboardInterrupt
。您可以通过安装和启用 win_unicode_console
或升级到 3.6
来解决此问题
问题是 Python 用于从控制台读取的旧代码取决于 ReadFile
在读取被 Ctrl+ 中断时将最后一个错误设置为 ERROR_OPERATION_ABORTED
(995) C。在 Windows 8 中,Microsoft 完全重写了客户端进程与控制台的通信方式。在这种情况下,他们这样做违反了 ReadFile
行为的记录合同。如果没有错误,Python 认为中止的读取是对 0 字节的成功读取。通常这表示文件结束 (EOF
),因此 REPL 会简单地退出,就像用户键入 Ctrl+Z、Enter 一样。
ReadFile
是从任何文件句柄的一般读取。还有一个专门的 ReadConsole
函数。这个仍然可以正常运行,这就是 win_unicode_console
和 3.6+ 没有这个问题的原因。他们调用 ReadConsoleW
来解决在控制台中使用全系列 Unicode 的单独问题,而这恰好也解决了 Ctrl+C 问题。
仅供参考,您在屏幕上看到的 ^C
不是由控制台 (conhost.exe) 或 Python 写入的。它实际上是由 cmd.exe shell 设置的 CTRL_BREAK_EVENT
处理程序打印的。如果您使用 PowerShell 运行 Python,您应该看不到使用 Ctrl+Break 打印的内容。
对于我使用过的大多数 Python 解释器,Ctrl+C 将使解释器打印出“KeyboardInterrupt
”并保持打开状态。但是,最近在新计算机上安装时,Ctrl+C 导致解释器退出,这是不可取的。
- 设置
signal.SIGINT
处理程序仍然存在。 - 没有 运行 可以调整行为的启动脚本。
raise KeyboardInterrupt
不退出解释器。- Ctrl+C 没有发出任何文本。在 Ctrl+Break 时,
^C
在退出前发出。
如果我在以下代码段的暂停期间按 Ctrl+C,解释器将保持打开状态。
import time
try:
time.sleep(100)
except KeyboardInterrupt:
pass
环境:Python 3.4.3 on Windows 10
当 Windows 8 及更高版本上 运行 时,shell 3.6 之前的 Python 版本的 Ctrl+C 处理被破坏。 input
和 raw_input
也被破坏了,你会得到 EOFError
而不是 KeyboardInterrupt
。您可以通过安装和启用 win_unicode_console
或升级到 3.6
问题是 Python 用于从控制台读取的旧代码取决于 ReadFile
在读取被 Ctrl+ 中断时将最后一个错误设置为 ERROR_OPERATION_ABORTED
(995) C。在 Windows 8 中,Microsoft 完全重写了客户端进程与控制台的通信方式。在这种情况下,他们这样做违反了 ReadFile
行为的记录合同。如果没有错误,Python 认为中止的读取是对 0 字节的成功读取。通常这表示文件结束 (EOF
),因此 REPL 会简单地退出,就像用户键入 Ctrl+Z、Enter 一样。
ReadFile
是从任何文件句柄的一般读取。还有一个专门的 ReadConsole
函数。这个仍然可以正常运行,这就是 win_unicode_console
和 3.6+ 没有这个问题的原因。他们调用 ReadConsoleW
来解决在控制台中使用全系列 Unicode 的单独问题,而这恰好也解决了 Ctrl+C 问题。
仅供参考,您在屏幕上看到的 ^C
不是由控制台 (conhost.exe) 或 Python 写入的。它实际上是由 cmd.exe shell 设置的 CTRL_BREAK_EVENT
处理程序打印的。如果您使用 PowerShell 运行 Python,您应该看不到使用 Ctrl+Break 打印的内容。