AIOHTTP-Client Quickstart

async with

 1import asyncio
 2import aiohttp
 3
 4
 5async def main():
 6    async with aiohttp.ClientSession() as session:
 7        async with session.get("http://httpbin.org/get") as resp:
 8            print(resp.status)
 9            print(await resp.json())
10
11asyncio.run(main())
  • 非同期のコンテキストマネージャ

  • ClientSessionを使った処理が終わったら session を close してくれる。

  • もし session context manager を使わない場合は以下のように .close() メソッドを呼び出し必ずクローズする。

 1import asyncio
 2import aiohttp
 3
 4
 5async def main():
 6    session = aiohttp.ClientSession()
 7    resp = await session.get("http://httpbin.org/get")
 8    print(await resp.json())
 9    await session.close()
10
11asyncio.run(main())

with文のネスト

async with (aiohttp.ClientSession() as session,
            session.get("http://httpbin.org/get") as resp):
            :
            :

async for

  • 非同期イテレータ/ジェネレータ用の for

  • 下記2つは同じ意味

async for a in async_iterable:
   await do_a_thing(a)
it = async_iterable.__aiter__()
while True:
   try:
      a = await it.__anext__()
   except StopAsyncIteration:
      break

   await do_a_thing(a)

ClientSession

  • aiohttp.ClientSession

  • クライアントセッションクラス。

  • インスタンス化して(以下 session で表現)、そのオブジェクトメソッドを使ってリクエストを行う

session.request()

  • aiohttp.ClientSession.request

  • 非同期のHTTPリクエストを実行

  • 引数(必須)
    • method (str) – HTTP method

    • url – URL。文字列もしくは yarl URL オブジェクト

  • オプション引数:ドキュメント参照

  • 返り値は aiohttp.ClientResponse インスタンスオブジェクト

session.get()

  • aiohttp.ClientSession.get

  • GET リクエスト

  • session.request() の第一引数が GET に固定されているメソッド

  • 引数(必須)
    • url – URL。文字列もしくは yarl URL オブジェクト

  • オプション引数:ドキュメント参照

  • 返り値は aiohttp.ClientResponse インスタンスオブジェクト

URLリクエストにパラメータ を渡す

 1import asyncio
 2import aiohttp
 3
 4
 5async def main():
 6    async with aiohttp.ClientSession() as session:
 7        params = {"limit": "10", "offset": "20"}
 8        async with session.get(
 9            "https://pokeapi.co/api/v2/pokemon", params=params
10        ) as resp:
11            print(resp.status)
12            print(await resp.json())
13
14
15asyncio.run(main())
16
  • params オプションで渡す

  • 同じキーに対して2つ以上の値を渡したい場合は、MultiDict もしくは、タプルのリストで渡す

    • MultiDict({'a': [1, 3]})

    • MultiDict([('a', 1), ('a', 3)])

    • ([('a', 1), ('a', 3)])

その他HTTPメソッド

ClientResponse

  • aiohttp.ClientResponse

  • session.request() とそのファミリーが返すクラス

  • API call だけがインスタンス化する(以下 resp と表現する)

  • ユーザがこのクラスをインスタンス化することは一切ない

  • コンテキストマネージャ async with での処理が完了すると release される

  • 主なインスタンスメソッド
    • resp.read() : レスポンス body を byte で読み込む。

    • resp.text(encoding=None): レスポンス body を文字列で読み込む。エンコーディング指定可

    • resp.json(encoding=None) : レスポンス body を JSON で読み込み、辞書型オブジェクトで返す。エンコーディング指定可

バイナリデータの読み込み

  • バイナリデータは .read() で取得可

 1import asyncio
 2import aiohttp
 3
 4
 5async def main():
 6    async with aiohttp.ClientSession() as session:
 7        async with session.get("https://pokeapi.co/api/v2/pokemon/25") as resp:
 8            html = await resp.json()
 9            async with session.get(html["sprites"]["front_default"]) as png:
10                with open("/tmp/pikachu.png", "wb") as f:
11                    f.write(await png.read())
12
13
14asyncio.run(main())

streaming response

  • read() json() text() は メモリにロードするので、巨大なサイズのファイルの読み込みには aiohttp.StreamReader のインスタンスの .content アトリビュートの利用を検討したほうがよい

  • よく使われる方法としては、chunk size を指定してファイル等に書き込むなどする

 1import asyncio
 2import aiohttp
 3
 4
 5async def main():
 6    async with aiohttp.ClientSession() as session:
 7        async with session.get("https://api.github.com/events") as resp:
 8            with open("/tmp/bigfile.txt", "wb") as f:
 9                while True:
10                    chunk = await resp.content.read(100)  # 100b, -1 ですべて
11                    # print(len(chunk))
12                    if not chunk:
13                        print("No chunk")
14                        break
15                    f.write(chunk)
16
17
18asyncio.run(main())

websockets

 1import asyncio
 2import aiohttp
 3
 4import logging
 5
 6logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s", datefmt="%X")
 7
 8
 9async def main():
10    async with aiohttp.ClientSession() as session:
11        async with session.ws_connect("wss://ftx.com/ws") as ws:
12            await ws.send_str('{"op":"ping"}')
13            # await ws.send_json({"op":"ping"})
14            msg = await ws.receive()
15            if msg.type == aiohttp.WSMsgType.TEXT:
16                logging.info(msg.json())
17
18asyncio.run(main())