aiohttp 运行时错误:await 未与 future 一起使用



我知道python asyncio - RuntimeError:await没有用于future,但是那里的答案并没有解决这里发生的事情。

使用aiohttp时,我遇到了以下错误:

File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/selector_events.py", line 485, in sock_connect
return await fut
RuntimeError: await wasn't used with future
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7fb28040f760>

以下是关联的代码:

urls = # some list of URLs including `https://www.alphavantage.co/query?function=OVERVIEW&symbol=IBM&apikey=demo`.....
async def run_tasks():
session = aiohttp.ClientSession()
tasks = [session.get(url) for url in urls]
await asyncio.gather(*tasks)
await session.close()
asyncio.run(run_tasks())

看起来我正在正确等待事件循环,但我不断遇到这个问题,什么给了?

版本:

aiohttp==3.7.4.post0
asyncio==3.4.3
Python 3.8.0

我知道这不能直接回答您的问题,但实际上aiohttp请求生命周期中有一些异步调用,因此您必须在几个地方await

import asyncio
import aiohttp
URL = "https://stackoverflow.com"

async def main():
session = aiohttp.ClientSession()
resp = await session.get(URL)
html = await resp.text()
print(f"{URL} <{resp.status}> ({len(html)})")
resp.release()
await session.close()

if __name__ == "__main__":
asyncio.run(main())

通常且更简单的方法是使用上下文管理器来确保正确关闭所有剩余资源:

import asyncio
import aiohttp
URLS = [
"https://serverfault.com",
"https://stackoverflow.com",
]

async def fetch(session, url):
async with session.get(url) as resp:
html = await resp.text()
print(f"{url} <{resp.status}>")
return {url: len(html)}

async def main():
tasks = []
async with aiohttp.ClientSession() as session:
for url in URLS:
tasks.append(asyncio.create_task(fetch(session, url)))
data = await asyncio.gather(*tasks)
print(data)

if __name__ == "__main__":
asyncio.run(main())

测试:

$ python test.py
https://serverfault.com <200>
https://stackoverflow.com <200>
[{'https://serverfault.com': 143272}, {'https://stackoverflow.com': 191046}]

这里有两件事可能发生:

  1. 你没有await你应该做的事情
  2. 您调用的 URL 是错误的请求,并且在您有机会查看真实情况之前,事件循环出错。

根据 aiohttp 文档

默认情况下,aiohttp 对 HTTPS 协议进行严格检查。可以通过将 ssl 设置为 False 来放宽认证检查

因此,您正在使用的urls很可能达到了此阈值,并且您被踢出局。更改行:

tasks = [session.get(url) for url in urls]

tasks = [session.get(url, ssl=False) for url in urls]

我知道这很旧 - 但我最近在 Python 脚本上遇到了同样的问题,并希望为寻求解决此问题的其他人留下一些有用的东西。这种无用的等待没有将来的错误没有出现在Windows或Linux上。我发现执行 ssl=False 确实解决了这个问题,但出于安全原因,我宁愿不关闭 SSL,所以我研究了 Mac OS X 环境中的证书问题。事实证明,对于Mac OS X上的Python3,您需要将SSL证书与Python3的安装过程分开安装,方法是转到应用程序->Python ->然后单击"安装证书.命令"以安装SSL证书,该证书允许Python使用SSL像在aiohttp中一样发出请求。希望这有助于其他人解决他们的错误。

下面是一个 Python 错误报告,其中特别提到了与 SSL 相关的证书问题: https://bugs.python.org/issue43404

最新更新