💨

pythonとjavascript 非同期処理の考え方、書き方

2024/02/17に公開

ふだんjavascriptを使っていて、pythonでの非同期処理の書き方を忘れるので、よく使うものだけをメモ。

croutineとPromise

JSでは「Promiseを返す関数」なんて表現されたりします。

3秒後に"Hello"を返す

const 3秒後にHelloを返す関数 = () =>{
  return new Promise((rosolve,reject)=>{
    setTimeout(()=>resolve('Hello'),3*1000)
  })
}

const greeting = await 3秒後にHelloを返す関数()

pythonではコルーチンと呼びます。
async awaitを使うにはasyncioというライブラリをインポートする必要があります。

import asyncio

async def 三秒後にHelloを返す関数():
    await asyncio.sleep(3)
    return 'Hello'

greeting = await 三秒後にHelloを返す関数()
print(greeting)

一つだけのリクエスト

nodejs

fetchを使っても書けますが、axiosのほうが使い勝手が良いので普通はaxiosをインポートして使います。

非同期処理なので、awaitを使ってresultが返ってくるのを待つ必要があります

await res = axios.get('')

// jsonの場合

pythonの場合

requestsを使います。

pythonは同期処理なので、awaitを使う必要はありません。

Promiseとコルーチン

awaitで待機させられる関数を、nodejsではPromiseを返す、pythonではTaskあるいはコルーチンを返すなどと表現することが多いです。

複数のリクエスト

通常、複数のリクエストを送る時は非同期処理をします。

非同期処理をせずに処理するというのは、例えて言うなら10通の手紙を出すのに、1通書いて投かんし返答が来てから2通目を書いて投かんしているようなものです。
非同期処理では10通をまとめて投かんし、(10秒で返却してくれる人もいれば、12秒で返却する人もいますし、20秒で返却する人もいます)全ての返答が揃ったら終了としますので、理論上は全ての処理が終わる時間イコール最もリードタイムの長い手紙(この場合は20秒)となります。

10件リクエストを送って、各リクエストの結果を配列にして返す処理を実装します。

JS

Promise.all()にPromiseを返す関数を配列でぶち込んで実行します。

const n秒後にnを返す関数 = async(n) =>{
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{
      resolve(n)
    },n*1000)
  })
}

const res = Promise.all([
  n秒後にnを返す関数(5),
  n秒後にnを返す関数(10)
])

console.log(res)

Python

非同期リクエストを送るにはaiohttpを、非同期的に処理するにはasyncioを使います。
(requestsとforでもできなくはないですが、無理してaiohttpを使わない理由はありません)

asyncio.gather()にコルーチンを集めて実行します

import asyncio

async def n秒後に返る関数(n):
    await asyncio.sleep(n)
    return n

async def main():
    return await asyncio.gather(
        n秒後に返る関数(5),
        n秒後に返る関数(10)
    )

res = await main()

print(res)

Discussion