Pythonで複数のhttpリクエストを同時に投げる
- 2020.11.30
- Web
あるプロダクトでGoogleのChat APIを使用した機能を作っていて、その際に、複数のAPIコールを並列で同時に投げたくて、そのやり方を調べて実装したのでメモ。
並列で複数処理を行う場合はasyncio.gatherを使う
Node.jsでいうPromise.all的な処理をPythonで行うには、asyncio.gatherを使います。以下、実装例です。
APIコールを呼び出す側のコード
import asyncio
tasks = [req(i) for i in range(3)]
results = await asyncio.gather(*tasks)
APIコールを行う側のコード(ここでは、APIコールの模擬として、time関数を使用)
import time
def req(i):
print(i, "start")
time.sleep(0.5)
print(i, "end")
return i
これだけで良いかと思いきや、結果は以下のようになり、並列でタスク実行できていないことがわかります。
0 start
0 end
1 start
1 end
2 start
2 end
なぜこのような結果になるかというと、Pythonのhttpリクエストで使用するrequestsというライブラリは、ノンブロッキングではないためです。
ブロッキングな処理を複数スレッドで実行するためにrun_in_executer()関数を使う
したがって、以下のようにrun_in_executer()関数を使うことで、別スレッドでの処理に変える必要があります。
APIコールを呼び出す側のコード
loop = asyncio.get_event_loop()
tasks = [async_req(loop, i) for i in range(3)]
resusts = await asyncio.gather(*tasks)
APIコールを行う側のコード(以下、別スレッドで実行するためのコードを追記)
async def async_req(loop, i):
return await loop.run_in_executor(None, req, i)
このようにすると、以下のように並列で処理を実行できていることがわかります。
0 start
1 start
2 start
0 end
1 end
2 end
-
前の記事
「初めての自動テスト」読書メモ 2020.11.24
-
次の記事
TypeScriptでDIしてみた 2021.02.08