为啥 asyncio 的事件循环会抑制 Windows 上的 KeyboardInterrupt?
Posted
技术标签:
【中文标题】为啥 asyncio 的事件循环会抑制 Windows 上的 KeyboardInterrupt?【英文标题】:Why does the asyncio's event loop suppress the KeyboardInterrupt on Windows?为什么 asyncio 的事件循环会抑制 Windows 上的 KeyboardInterrupt? 【发布时间】:2014-12-15 09:32:42 【问题描述】:我有一个非常小的测试程序,除了执行asyncio
事件循环之外什么都不做:
import asyncio
asyncio.get_event_loop().run_forever()
当我在 Linux 上运行此程序并按 Ctrl+C 时,程序将正确终止并出现 KeyboardInterrupt
异常。在 Windows 上按 Ctrl+C 什么都不做(用 Python 3.4.2 测试)。即使在 Windows 上,带有 time.sleep()
的简单无限循环也会正确引发 KeyboardInterrupt
:
import time
while True:
time.sleep(3600)
为什么 asyncio 的事件循环会抑制 Windows 上的 KeyboardInterrupt?
【问题讨论】:
【参考方案1】:有适用于 Windows 的解决方法。运行另一个 corouting 每秒唤醒循环并允许循环对键盘中断做出反应
来自异步文档的 Echo 服务器示例
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
【讨论】:
【参考方案2】:这是一个错误,当然。
问题解决进度见issue on python bug-tracker。
【讨论】:
Windows 上的 Ctrl-C 将在 Python 3.8 中运行? docs.python.org/dev/whatsnew/3.8.html#asyncio【参考方案3】:如果您只想退出程序而不需要捕获KeyboardInterrupt
,signal 模块提供了一种更简单(更高效)的解决方法:
# 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()
【讨论】:
此解决方案是否清理套接字连接? @Jiu 这只是导致进程退出。操作系统将关闭任何打开的套接字。请参阅superuser.com/questions/375604 了解更多信息。以上是关于为啥 asyncio 的事件循环会抑制 Windows 上的 KeyboardInterrupt?的主要内容,如果未能解决你的问题,请参考以下文章