Pythonの非同期プログラミング,イベントループについて

async def asyc_hello():
   print("Hello")
asyc_hello()

実行結果(コルーチンオブジェクトを返す)

<coroutine object asyc_hello at 0x7fbf491059c0>

asyncはdefの前に用いて,コルーチン(並行task)を定義する.コルーチン関数の実行は定義された状況に応じて中断・再開が可能.asyncで定義された関数を呼び出されてもその場では関数の実行は行わず,小ルーチンオブジェクトというものを返す.asyncで定義された関数を呼び出されてもその場では関数の実行は行わず,コルーチンオブジェクトというものを返す.

import asyncio
async def asyncio_hello():
   print("こんにちは")
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio_hello())じ

実行結果

こんにちは

コルーチンオブジェクトを実行するためには,イベントループというものを作る必要がある.以下のコードでは,asyncio.get_event_loop()によってイベントループを作成し,run_until_complete(asyncio_hello())によって,corutine objectを実行する.

Even loopについて

画像1

コルーチンオブジェクトについて

コルーチンオブジェクトは,イベントループの中で実行されるものになる.イベントループの中ではキューが貯められていて,順番が来るまでコルーチンオブジェクトは何もしない.

import asyncio

async def print_number(number):
   print(number)

if __name__ == "__main__":
       loop=asyncio.get_event_loop()
       task=asyncio.wait([print_number(number)
                          for number in range(10)
                         ])
       loop.run_until_complete(task)

実行結果

1
2
0
4
6
8
9
7
5
3

コードの基本的な流れ:

1.イベントループを作成する:

asyncio.get_event_loop()

2.タスクを作成or追加する:

asyncio.get_event_loop().create_task()

or

asyncio.wait()

3.イベントループを実行する:

asyncio.get.event_loop().run_until_complete()

*最後のasyncio.get_event_loop().close()は不要.

次に,awaitについて説明します.まず,asyncio.wait()awaitという予約語を付与した場合の例になります.

import time
import random
import asyncio

async def waiter(name):
   for _ in range(4):
       time_to_sleep=random.randint(1,3)/4
       time.sleep(time_to_sleep)
       print(
       "{}は{}秒待ちました".format(name,time_to_sleep))
async def main():
   await asyncio.wait([waiter("foo"),waiter("bar")])
if __name__ == "__main__":
   loop = asyncio.get_event_loop()
   loop.run_until_complete(main())

awaitはコルーチンが実行を返すのを待って,実行が終わるまで制御を解放してイベントループに渡します.time.sleep()関数によって,処理がブロックされるので,同期処理になり,順番に処理が実行されます.(処理を待たずに,リクエストされたものから順番に処理を実行)一方,asyncio.sleep()を使えば,非同期処理の実行が可能になります.

import time 
import random
import asyncio

async def waiter(name):
   for _ in range(4):
       time_to_sleep = random.randint(1,3)/4
       time.sleep(time_to_sleep)
       await asyncio.sleep(time_to_sleep)
       print(
           "{}は{}秒待ちました"
           "".format(name, time_to_sleep)
       )

async def main():
   task=[waiter("foo"), waiter("bar")]
   await asyncio.wait(task)

if __name__ == "__main__":
   loop = asyncio.get_event_loop()
   loop.run_until_complete(main())

実行結果

barは0.75秒待ちました
fooは0.5秒待ちました
barは0.25秒待ちました
fooは0.25秒待ちました
barは0.5秒待ちました
fooは0.5秒待ちました
barは0.25秒待ちました
fooは0.75秒待ちました

ご覧のようにbarとfooが交互に繰り返されていて,処理速度が向上しています.コルチーンが協調的に制御を解放したということを意味します.







この記事が気に入ったらサポートをしてみませんか?