今回は、Webcomicを提供しているAPIからコミック画像を取得してブラウザに表示するプログラムを通して、flask2.0での非同期処理の使い方を紹介していきます。
app.py
# pip install httpx
# pip install flask
# pip install flask[async]
from flask import Flask
import httpx
import asyncio
from random import randint
app = Flask(__name__)
async def get_image(client):
""" 非同期で行いたい処理 """
random = randint(0, 300)
# APIに通信
result = await client.get(f'http://xkcd.com/{random}/info.0.json')
# 画像のURLのみ返す
return result.json()['img']
@app.get('/async_api')
async def async_api():
# httpxで非同期通信
async with httpx.AsyncClient() as client:
# 非同期の対象処理をリストにまとめる
tasks = [get_image(client) for _ in range(5)]
# 非同期処理の結果を受け取る
urls = await asyncio.gather(*tasks)
html = ""
for url in urls:
html += f"<img src='{url}'><br><br>"
return html
app.pyのあるディレクトリに移動してflask run
を実行し、http://127.0.0.1:5000/async_api にアクセスすると、APIで取得したコミック画像が表示されます。ただ、これだけだと同期通信との違いは分からないので、比較するために同期通信のプログラムもapp.pyに追加します。
app.py
....
@app.get('/sync')
def sync():
urls = []
for _ in range(5):
random = randint(0, 300)
response = httpx.get(f'http://xkcd.com/{random}/info.0.json')
urls.append(response.json()['img'])
html = ""
for url in urls:
html += f"<img src='{url}'><br><br>"
return html
同様にflask run
を再実行し、http://127.0.0.1:5000/async_api とhttp://127.0.0.1:5000/sync で画像の表示速度を比べてみてください。定量的に比較したい方は処理にかかる時間を表示できるようにしてみるとよいかもしれません。
今回紹介した非同期処理ですが、CPUに待ち時間が発生するI/O処理では速度が上がりますが、CPUに依存する処理を対象にしても処理速度は速くならないと思うので注意してください。