Jay*_*K23 9 python python-3.x python-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())
Run Code Online (Sandbox Code Playgroud)
这是输出:
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Run Code Online (Sandbox Code Playgroud)
我不明白为什么我会收到这个错误,有人可以帮我解决这个问题吗?
我终于想出了如何继续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()
Run Code Online (Sandbox Code Playgroud)
此代码将检查 newEventLoop是否为ProactorEventLoop.
如果是这样,永远保持循环直到proactor_wrap等待main和调度循环停止。
否则——可能是除 Windows 之外的所有其他操作系统——不需要这些额外的步骤,只需调用即可asyncio.run()。
像 Pycharm 这样的 IDE 会抱怨传递AbstractEventLoop给ProactorEventLoop参数,可以安全地忽略。
虽然这已得到答复并接受。您可以通过一行代码解决此问题:asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
Event loop is closed是 Windows 上的一个已知问题(请参阅https://github.com/encode/httpx/issues/914)。我怀疑这个问题会在 Python 的更高版本中得到修复。要解决该错误,只需将事件循环策略设置为 WindowsSelectorEventLoopPolicy 即可。
如果您打算在非Windows环境下运行代码;那么你需要添加一个 if 语句来防止错误。例如:if sys.platform == 'win32'。或者添加代码来设置策略。
工作示例:
import asyncio
from aiocfscrape import CloudflareScraper
import sys
async def nested(url):
async with CloudflareScraper() as session:
async with session.get(url) as resp:
print(resp.status)
return await resp.text()
async def main():
URL = "https://www.binance.com/api/v3/exchangeInfo"
await asyncio.gather(nested(URL), nested(URL), nested(URL))
# Only preform check if your code will run on non-windows environments.
if sys.platform == 'win32':
# Set the policy to prevent "Event loop is closed" error on Windows - https://github.com/encode/httpx/issues/914
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)