pythonとjavascript 非同期処理の考え方、書き方
ふだん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