使用asyncio.run()时关闭Asyncio事件循环
问题描述
我正在开始使用AsyncIO和AioHTTP,并且我正在编写一些基本代码来熟悉语法。我尝试了以下应同时执行3个请求的代码:
import time
import logging
import asyncio
import aiohttp
import json
from aiohttp import ClientSession, ClientResponseError
from aiocfscrape import CloudflareScraper
async def nested(url):
async with CloudflareScraper() as session:
async with session.get(url) as resp:
return await resp.text()
async def main():
URL = "https://www.binance.com/api/v3/exchangeInfo"
await asyncio.gather(nested(URL), nested(URL), nested(URL))
asyncio.run(main())
以下是输出:
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
我不明白为什么会出现该错误,有人能帮我解决这个问题吗?
解决方案
更新
请考虑使用Trio而不是异步,这样更稳定、更一致。
import trio
async def task():
await trio.sleep(5)
trio.run(task)
如果不能回答,请检查下面Greg的答案
import asyncio
import sys
if sys.platform:
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
原始帖子
我终于知道如何保持ProactorEventLoop
运行,防止IO关闭失败。
我真的不确定为什么Windows的事件循环如此错误,因为asyncio.open_connection
和asyncio.start_server
也会发生这种情况。
若要解决此问题,您需要在永久循环中运行事件循环并手动关闭。
以下代码将涵盖Windows和其他环境。
import asyncio
from aiocfscrape import CloudflareScraper
async def nested(url):
async with CloudflareScraper() as session:
async with session.get(url) as resp:
return await resp.text()
async def main():
await nested("https://www.binance.com/api/v3/exchangeInfo")
try:
assert isinstance(loop := asyncio.new_event_loop(), asyncio.ProactorEventLoop)
# No ProactorEventLoop is in asyncio on other OS, will raise AttributeError in that case.
except (AssertionError, AttributeError):
asyncio.run(main())
else:
async def proactor_wrap(loop_: asyncio.ProactorEventLoop, fut: asyncio.coroutines):
await fut
loop_.stop()
loop.create_task(proactor_wrap(loop, main()))
loop.run_forever()
此代码将检查新的EventLoop
是否为ProactorEventLoop
。如果是,则一直保持循环,直到
proactor_wrap
等待main
并计划停止循环。
否则-可能是Windows以外的所有其他操作系统-不需要这些额外步骤,只需调用asyncio.run()
即可。
像PyCharm这样的IDE会抱怨将AbstractEventLoop
传递给ProactorEventLoop
参数,可以安全地忽略。
相关文章