【问题标题】:ctrl-C doesn't work after calling second new_event_loop()调用第二个 new_event_loop() 后 ctrl-C 不起作用
【发布时间】:2022-12-31 21:15:13
【问题描述】:
我无法用 ctrl-C 终止下面的程序:
import asyncio
loop1 = asyncio.new_event_loop()
asyncio.set_event_loop(loop1)
loop2 = asyncio.new_event_loop()
loop1.run_forever()
但是,我可以终止下面的程序:
import asyncio
# execute this first
loop2 = asyncio.new_event_loop()
loop1 = asyncio.new_event_loop()
asyncio.set_event_loop(loop1)
loop1.run_forever()
为什么?
(我在 python 3.11.1,windows 中运行这些)
【问题讨论】:
标签:
python
python-asyncio
【解决方案1】:
这两种方法都不是构建事件循环的正确方法,应该避免这两种方法,启动事件循环的官方方法是使用 asyncio.run() 和协程。
您看到的这种行为特定于 Windows,其中 asyncio 将当前信号处理程序文件描述符设置为使用 signal.set_wakeup_fd 中断最后创建的循环的文件描述符,因此中断信号被发送到循环 2 的文件描述符,当循环 1 由进程提供服务并且不处理操作系统发送的那些信号时,您可以在 Handling Keyboard Interruption 中阅读有关 asyncio 处理键盘中断的方式的更多信息
为避免所有这些问题,您应该使用官方方式启动事件循环,即:asyncio.run(main()) 和 asyncio documentation 中一样,并避免自己创建循环,否则您会遇到各种麻烦。 (孤立的任务、错误的文件描述符、未处理的信号等)或者只是避免创建多个事件循环,并自己处理创建循环的所有相关后果。
应用程序开发人员通常应该使用高级异步
函数,例如 asyncio.run(),应该很少需要引用
循环对象或调用其方法。本节主要用于
对于底层代码、库和框架的作者,他们需要
更好地控制事件循环行为。
import asyncio
async def main():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
asyncio.run(main())