1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

asyncio を利用して非同期http通信を実現する

Last updated at Posted at 2020-04-22

背景

例えばエッジ端末で物体検知を行い続け、処理結果をサーバに送信したいとする.
detectionのループ処理中の間にHTTP POST処理を挟むと、レスポンスが帰ってくるまで処理が止まってしまう。
python標準のasync/awaitを利用することで、非同期通信が実現できる。その使い方をまとめる。

参考サイト

環境

  • python3.7.3

処理の流れ

import asyncio
import aiohttp

def say_something(future):    # 5
    print(future.result())
    return 'hello!'


async def nested(counter):
    return counter


async def test():
    await asyncio.sleep(2)    # 3
    return'aaaaaaaaaaaaaaaaaaaa'


async def main():
    rep = 0
    counter = 0
    while True:

        if (counter % 100 == 0) and (counter != 0):
            http_req = asyncio.create_task(test())    # 2
            http_req.add_done_callback(say_something)    # 4
            counter = 0
            print(f'rep: {rep}')
            rep += 1

        task = asyncio.create_task(nested(counter))

        print(await task)

        counter += 1


asyncio.run(main())    # 1

async とは

コルーチン(coroutin)を定義するための宣言。
コルーチンはサブルーチンのより一般的な形で、エントリポイントを複数個もつことができる。つまり、処理を中断してその場所から再開することができる。

イベントループとは

タスクスケジューラーのようなイメージで良い。イベントループに対してコルーチンを登録することで、実行・停止・再処理を自動で行ってくれる。

処理の中身

  1. asyncio.runでイベントループにmainコルーチンを登録する。
  2. mainコルーチンの内部では、特定条件の時にさらに別のコルーチンtest()をイベントループに登録する。test()は登録と同時に並列で処理が開始される。
  3. test()内部では、await asyncio.sleep(2)によって「2秒間待つ」という処理が行われる。
  4. main()の処理は止まらないが、今登録したtest()=http_reqが終了した際に実行するコールバック関数を定義する。
  5. コールバック関数は、futureオブジェクト(http_reqの実体みたいなもの)の結果を標準出力に表示する。
    ※ asyncio.create_task()の返り値はfutureオブジェクトで、これは処理が完了した時にその返り値を自動的に自身に登録する。.result()で呼び出せる。
  6. 特定条件下にない時も同様にイベントループに処理を登録して、実行する。で、whileループが継続する。

実装時の注意点

httpリクエストはrequestsライブラリを使わず、aiohttpというライブラリを使った。

$ pip install aiohttp

以下のような形でHTTPリクエストをコルーチンとして登録できる。

async def process_http_request(data):
    async with aiohttp.ClientSession() as session:
        async with session.post(URL, json=data) as response:
            return await response.text()

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?