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 でもやってみたところ出来ました。
(実はpython3.9でも可)
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¶
クライアントセッションクラス。
インスタンス化して(以下
session
で表現)、そのオブジェクトメソッドを使ってリクエストを行う
session.request()¶
非同期のHTTPリクエストを実行
- 引数(必須)
method (str)
– HTTP methodurl
– URL。文字列もしくは yarl URL オブジェクト
オプション引数:ドキュメント参照
返り値は aiohttp.ClientResponse インスタンスオブジェクト
session.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メソッド¶
返り値は aiohttp.ClientResponse インスタンスオブジェクト
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())
client session を確立後、aiohttp.ClientSession.ws_connect() メソッドでウェブソケットへ接続
URL を渡して初期化すると、ウェブソケットサーバーに接続状態になる。返り値は aiohttp.ClientWebSocketResponse 。(以下
ws
で表現)ws.send_str() メソッドで ping を投げて ws.receive() メソッドでレスポンスを待つ。
ws.send_json() メソッドで json を投げることも可
ws.receive() の返り値は aiohttp.WSMessage オブジェクト。その
type
属性が aiohttp.WSMsgType で、そのタイプによって処理を切り分ける