aiohttp RuntimeError: await wasn't used with future

Question:

I’m aware of python asyncio – RuntimeError: await wasn't used with future, however the answer there doesn’t address what went on here.

When using aiohttp I ran across the following error:

  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>

Here is the code associated:

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())

It looks like I am awaiting the event loop properly, but I keep hitting this issue, what gives?

Versions:

aiohttp==3.7.4.post0
asyncio==3.4.3
Python 3.8.0
Asked By: Patrick Collins

||

Answers:

There are 2 things that could be happening here:

  1. You are not awaiting something that you should be
  2. The URLs you’re calling are bad requests, and the event loop is erroring before you get a chance to see what’s really going on.

According to the aiohttp documentation

By default aiohttp uses strict checks for HTTPS protocol. Certification checks can be relaxed by setting ssl to False

So it’s likely that the urls that you’re using are hitting this threshold, and you’re getting kicked out. Change the line:

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

to

tasks = [session.get(url, ssl=False) for url in urls]
Answered By: Patrick Collins

I know this doesn’t answer your question directly but there are actually a few asynchronous calls in aiohttp request life-cycle so you’ll have to await in a few places:

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())

The usual and easier approach is to use context managers that will ensure all remaining resources are closed correctly:

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())

Test:

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

I know this is old- but I ran into this very same issue on a Python script recently and hoped to leave something helpful for others looking for a resolution to this problem. This unhelpful await without future error did not appear on Windows or Linux. I discovered that doing ssl=False did indeed fix the issue, but I preferred not to turn SSL off for security reasons, so I looked into certificates issues on Mac OS X environments. It turns out for Python3 on Mac OS X you need to install SSL Certificates separately from the installation process for Python3, by going to Applications -> Python -> and then clicking on "Install Certificates.command" to install the SSL certificates that allows Python to use SSL to make requests like in aiohttp. Hope this helps someone else resolve their errors.

Here is a Python bug report that specifically mentions the certificates issue related to SSL:
https://bugs.python.org/issue43404

Answered By: duckduckgrayduck
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.