ClientSession and your first request

aiohttp · Essentials · 9 min

Every aiohttp client program is built around one long-lived session, so the pattern has to be right from the start.

aiohttp is async-only: every request is awaited inside a coroutine run by asyncio. Install it with pip install aiohttp.

The central object is aiohttp.ClientSession. It owns a connection pool, cookies and default settings, and it must be created inside a running event loop (inside an async def) and closed when you are done. The idiom is nested async with blocks:

async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
        data = await resp.json()

The outer block closes the session and its connections. The inner block makes the request: session.get(...) sends it and returns once the status line and headers have arrived; the body is read separately with await resp.text(), await resp.json() or await resp.read(). Leaving the inner block releases the connection back to the pool.

Methods mirror HTTP verbs: session.get, post, put, patch, delete, head, options, plus session.request(method, url). Data options include params=, headers=, json= and data=.

Rules from the official docs: create one session per application (or per group of related requests) and reuse it; do not create a session per request, which throws away connection pooling and is slow. Also, there is no top-level aiohttp.get function for good reason: always go through a session.

To start the program, call asyncio.run(main()).

Example

import asyncio
import aiohttp

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get("https://httpbin.org/get", params={"q": "aio"}) as resp:
            print(resp.status)                  # 200
            data = await resp.json()
            print(data["args"])                 # {'q': 'aio'}

        async with session.post("https://httpbin.org/post", json={"x": 1}) as resp:
            print((await resp.json())["json"])  # {'x': 1}

asyncio.run(main())

Remember

  • Create one ClientSession inside async code and reuse it
  • async with session.get(...) as resp, then await resp.json()/text()/read()
  • Leaving the blocks releases connections and closes the session

Watch out for

  • Creating a new ClientSession for every request.

Check yourself

  1. Why does `data = resp.json()` (without await) not give you the data?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.aiohttp.org/en/stable/client_quickstart.html