关于python:为什么asyncio的事件循环会抑制Windows上的KeyboardInterrupt?

Why does the asyncio's event loop suppress the KeyboardInterrupt on Windows?

我有一个非常小的测试程序,除了执行asyncio事件循环外,它什么也不做:

1
2
import asyncio
asyncio.get_event_loop().run_forever()

当我在Linux上运行该程序并按Ctrl + C时,该程序将正确终止,并出现KeyboardInterrupt异常。 在Windows上,按Ctrl + C不会执行任何操作(使用Python 3.4.2测试)。 time.sleep()的简单无限循环即使在Windows上也可以正确地提高KeyboardInterrupt

1
2
3
import time
while True:
    time.sleep(3600)

为什么异步事件循环会抑制Windows上的KeyboardInterrupt?


当然,这是一个错误。

有关解决问题的进度,请参见python bug-tracker上的问题。


Windows有解决方法。 运行另一个程序,该程序每秒唤醒一次循环,并允许循环在键盘中断时做出反应

来自asyncio doc的Echo服务器示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
async def wakeup():
    while True:
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)

# add wakeup HACK
loop.create_task(wakeup())

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

如果您只想退出程序而不需要捕获KeyboardInterrupt,则信号模块提供了一种更简单(更有效)的解决方法:

1
2
3
4
5
6
7
# This restores the default Ctrl+C signal handler, which just kills the process
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

# Now the event loop is interruptable
import asyncio
asyncio.get_event_loop().run_forever()