异步事件循环已关闭:获取循环时

119

当尝试运行文档中给出的asyncio hello world代码示例时:

import asyncio

async def hello_world():
    print("Hello World!")

loop = asyncio.get_event_loop()
# Blocking call which returns when the hello_world() coroutine is done
loop.run_until_complete(hello_world())
loop.close()

我遇到了一个错误:


RuntimeError: Event loop is closed

我正在使用Python 3.5.3。


这个回答解决了你的问题吗?Asyncio RuntimeError: Event Loop is Closed - Arhadthedev
3个回答

178

在Windows上似乎存在EventLoopPolicy的问题,使用这段代码来解决:

asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())

17
谢谢,但你是怎么发现这件事的? - Shryder
6
在升级 Python 后,我的功能代码开始抛出这个错误。我查看了 Python 版本之间的更改,并发现默认的 EventLoopPolicy 已被替换(在文档中提到过)。请您帮忙检查一下。 - j4hangir
3
如果您使用 asyncio.run 函数,它会关闭事件循环。 - Ahmed
1
@j4hangir,有时候你不想关闭事件循环并且希望重复使用它。我曾经遇到过一个错误,在重复使用事件循环时不得不回退到asyncio.get_event_loop() - Ahmed
1
即使使用asyncio.run,我仍然需要设置循环策略才能使其正常工作。Py3.10 - TASC Solutions
1
哇,谢谢!我一直在尝试修复这个错误。在这里留下评论,以防有人在使用Python和pg8000连接GCP Cloud SQL postgres时遇到相同的错误。只需导入asyncio并将此行放在顶部即可解决问题。 - weezilla

108

在全局事件循环中,您已经调用了loop.close(),然后才运行示例代码:

>>> import asyncio
>>> asyncio.get_event_loop().close()
>>> asyncio.get_event_loop().is_closed()
True
>>> asyncio.get_event_loop().run_until_complete(asyncio.sleep(1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python3.6/asyncio/base_events.py", line 443, in run_until_complete
    self._check_closed()
  File "/.../lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

您需要创建一个新的循环:

loop = asyncio.new_event_loop()

您可以使用以下代码将其设置为新的全局循环:

asyncio.set_event_loop(asyncio.new_event_loop())

然后只需再次使用 asyncio.get_event_loop()

或者,重新启动您的Python解释器,第一次尝试获取全局事件循环时,您将获得一个新的、未关闭的事件循环。

自Python 3.7以来,创建、管理和关闭事件循环(以及其他一些资源)的过程在使用asyncio.run()时由Python为您处理。它应该代替loop.run_until_complete(),不再需要先获取或设置事件循环。


5
如果你仍然收到“Event loop is closed”错误提示,那么你的代码可能在使用旧的事件循环句柄。 - fuzzyTew
有没有想法为什么从这个输出和代码还是无法正常工作?https://pastecode.io/s/894dr1o4 - Lod
1
@Lod它确实起作用了。错误是事件循环清理钩子中的异常。看起来有点凌乱,这是由于已知的aiohttp bug与Windows asyncio循环实现相互作用所致,但你的代码起作用了。这就是为什么输出以3开头,然后是Exception ignored部分。 - Martijn Pieters

29

...以防万一:

import platform
if platform.system()=='Windows':
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

如果您曾将代码部署到云端,那么它可能会避免痛苦的调试。


Windows事件循环在文件描述符数量上有非常严格的限制,https://dev59.com/dafja4cB1Zd3GeqPt1Gf - Gryu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接