0
0

More than 1 year has passed since last update.

asyncとawaitの基本的な使い方

Posted at

今回もメモ用。
自分なりの解釈です。

概要

asyncとawaitの基本的な使い方です。

とりあえず、以下を書いてみます。
asyncとawaitを使用すると、非同期処理が実装できます。
asyncをつけた関数をコルーチン関数と呼びます。
awaitでコルーチン関数を呼び出してしようします。

内容

とりあえず、test1~test3を順番通り実行してみます。

asyncawait.py
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を実行させる場合、並行処理させる必要があります。
その場合、以下の様にします。

asyncawait.py
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()で実行します。

asyncawait-loopevent.py
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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0