今回もメモ用。
自分なりの解釈です。
概要
asyncとawaitの基本的な使い方です。
とりあえず、以下を書いてみます。
asyncとawaitを使用すると、非同期処理が実装できます。
asyncをつけた関数をコルーチン関数と呼びます。
awaitでコルーチン関数を呼び出してしようします。
内容
とりあえず、test1~test3を順番通り実行してみます。
import asyncio
async def test1(num):
print(num + 10)
await asyncio.sleep(5)
print("test1")
async def test2(num):
print(num + 0)
await asyncio.sleep(5)
print("test2")
async def test3(num):
print(num + 20)
await asyncio.sleep(5)
print("test3")
async def main():
await test1(10)
await test2(10)
await test3(10)
asyncio.run(main())
以下、実行結果です。
20
test1
10
test2
30
test3
asyncio.run(main())では、コルーチン関数main()を実行しています。
※asyncio.run()は一時的にイベントループを作成し、そこに引数で指定したコルーチン関数を入れ、
イベントループを実行し、コルーチン関数が終了すると、勝手にループを閉じます。
main関数内でtest1を実行→実行待ち→実行完了→test2を実行→実行待ち→実行完了→test3を実行→実行待ち→実行完了となります。これはawait test1(10)を実行するとmain関数がtest1が完了するまで、その他の処理を受け付けず、
順番通り処理を実行させることができます。
これを、test1実行中にtest2を実行させる場合、並行処理させる必要があります。
その場合、以下の様にします。
import asyncio
async def test1(num):
print(num + 10)
#test1の処理を5秒停止します。
await asyncio.sleep(5)
print("test1")
async def test2(num):
print(num + 0)
#test2の処理を5秒停止します。
await asyncio.sleep(5)
print("test2")
async def test3(num):
print(num + 20)
#test3の処理を5秒停止します。
await asyncio.sleep(5)
print("test3")
async def main():
#コルーチンをループに追加し、asyncio.Taskを作成。
exetask1 = asyncio.create_task(test1(10))
exetask2 = asyncio.create_task(test2(10))
exetask3 = asyncio.create_task(test3(10))
#各asyncio.Taskを並列実行しますが、出力は第一引数からとなります。
await asyncio.gather(exetask1,exetask2,exetask3)
#mainコルーチン関数をループに入れて実行
asyncio.run(main())
こうすると、asyncio.run()で一時的に作成したイベントループにasyncio.create_task(tasks)でコルーチンオブジェクトをスケジュールします。await asyncio.gather(exetask1,exetask2,exetask3)で、指定した3つのタスク(exetask1,exetask2,exetask3)の処理が完了するまで、main関数の処理の受付を停止します。
各タスク内で、await asyncio.sleep(5)を実行していますが、これはタスクの処理を一時停止します。
なので、並行処理をしている別のタスクを実行することができます。
そのため、以下のような結果になります。
20
10
30
test1
test2
test3
補足
ループイベントを任意に作成することもできます。
作成した、ループイベントをloop.run_until_complete()で実行します。
import asyncio
async def test1(num):
print(num + 10)
await asyncio.sleep(5)
print("test1")
async def test2(num):
print(num + 0)
await asyncio.sleep(5)
print("test2")
async def test3(num):
print(num + 20)
await asyncio.sleep(5)
print("test3")
#ループイベントを作成します。
loop = asyncio.new_event_loop()
#ループイベントをカレントループイベントとして設定します。
asyncio.set_event_loop(loop)
#作成したループイベントに追加し、タスクを作成します。
exetask1 = loop.create_task(test1(10))
exetask2 = loop.create_task(test2(10))
exetask3 = loop.create_task(test3(10))
#コルーチン関数を指定して、最後まで実行します。
loop.run_until_complete(asyncio.gather(exetask1,exetask2,exetask3))
#ループイベントを閉じます。
loop.close()
参考URL