0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python3 非同期処理のイベントループとは何か

Posted at

イベントループとは?

イベントループは、非同期処理を管理する仕組みで、タスク(イベント)を順番に処理するためのループです。名前の通り、イベント(非同期タスク)がキューに追加され、それをループしながら処理していく様子を表しています。

Pythonでは、asyncioモジュールを使って非同期処理を実現します。このモジュールの中心的な役割を果たすのがイベントループです。

イベントループの動作イメージ

イベントループは以下のように動作します:

  1. タスクの登録: 非同期関数(async defで定義された関数)の戻り値であるコルーチンオブジェクトがイベントループにタスクとして登録されます。登録されたタスクはタスクキューに追加されます。
  2. タスクの実行: イベントループはタスクキューからタスクを1つずつ取り出して実行します。
  3. 待機状態のタスク: タスクがawaitで待機状態になると、イベントループはそのタスクを一時停止し、他のタスクを実行します。
  4. タスクの再開: 待機状態が解除されると、タスクは再びタスクキューに戻され、実行が再開されます。

キューの役割

イベントループが内部で使用するキュー(FIFO)には以下のような役割があります。

  • タスクキュー:
    • 実行待ちの非同期タスクを処理します
    • タスクが完了するか、待機状態になるまで順番に実行されます。
  • イベントキュー:
    • I/O操作やタイマーイベントなど、外部から発生したイベントを管理します。
    • イベントが発生すると、対応するコールバックがタスクキューに追加されます。

1. タスクキュー(Task Queue)

  • 主な役割: 非同期で実行すべき「タスク」(関数やコールバック)を順番に管理するキューです。
  • : Pythonのasyncioではawaitで待機しているコルーチンなどがタスクキューに入ります。
  • イベントループの動作: イベントループはタスクキューからタスクを1つずつ取り出して実行します。

2. イベントキュー(Event Queue)

  • 主な役割: 外部から発生した「イベント」(I/O完了通知、ユーザー操作、ネットワーク受信など)を管理するキューです。
  • : ファイルの読み込み完了、ソケット通信の受信、ユーザーのクリックイベントなど。
  • イベントループの動作: イベントループはイベントキューからイベントを取り出し、それに対応するコールバックやタスクをタスクキューに追加します。

Python(asyncio)の場合

  • タスクキュー: 実行待ちのコルーチンやコールバックが入る。
  • イベントキュー: OSやライブラリが通知するI/Oイベントなどが入る(内部的にはselectorなどで管理)。
  • asyncioのイベントループは、I/Oイベントを検知すると対応するコールバックをタスクキューに追加し、順次実行します。

Pythonでのイベントループの例

以下はPythonでイベントループを使った非同期処理の例です:

import asyncio

async def task1():
    print("Task 1: 開始")
    await asyncio.sleep(2)  # 非同期で2秒待機
    print("Task 1: 終了")

async def task2():
    print("Task 2: 開始")
    await asyncio.sleep(1)  # 非同期で1秒待機
    print("Task 2: 終了")

async def main():
    # タスクをイベントループに登録
    await asyncio.gather(task1(), task2())

# イベントループを開始
asyncio.run(main())

実行結果

Task 1: 開始
Task 2: 開始
Task 2: 終了
Task 1: 終了

動作の流れ

  1. task1, task2がイベントループに登録され、タスクキューに追加されます。
  2. イベントループがタスクキューからタスクを取り出して実行します。
  3. await asyncio.sleep() によってタスクが待機状態になると[待機中のタスクリスト]にタスクが登録され、他のタスクが実行されます。
  4. await待機が終了すると[待機中のタスクリスト]からタスクが再びタスクキューに戻され、実行が再開されます。

イベントループの特徴

  • イベントループは1つのスレッドで動作します(シングルスレッド)。
  • 非同期処理を効率的に管理し、I/O待機中でも他のタスクを実行できます。

イベントループは「イベントがループしている様子」を表していると言えますが、実際には「登録された非同期タスクを順番に処理する仕組み」を指します。

Q. ループしていないのになぜイベントループという名称がつけられているのですか?

A. イベントループという名称がつけられている理由は、イベントを処理する仕組みが「ループのように繰り返し動作する」 からです。実際には、イベントループは内部的に繰り返し処理を行っているため、「ループしていない」というわけではありません。

イベントループの動作

イベントループは以下のような流れで動作します:

  1. イベントキューを監視: イベントループは、非同期タスクやI/O操作の完了通知などが登録される「イベントキュー」を監視します。
  2. イベントの取り出し: キューにイベントがある場合、それを取り出して処理します。
  3. 処理の繰り返し: キューが空になるまで、またはプログラムが終了するまで、この処理を繰り返します。

この「イベントキューを監視し、イベントを処理する」という動作が、ループのように繰り返されるため、「イベントループ」と呼ばれています。

実際のループの例

イベントループは内部的には、以下のような仕組みで動作しています(擬似コード):

while True:  # 無限ループ
    event = get_next_event()  # キューから次のイベントを取得
    if event:
        process_event(event)  # イベントを処理
    else:
        wait_for_event()  # イベントが来るまで待機

このように、イベントループは実際に「ループしている」仕組みを持っています。

まとめ

イベントループという名称は、内部的にイベントを処理する仕組みが「ループのように繰り返し動作する」ことに由来しています。開発者が直接ループを記述しない場合でも、イベントループは裏で繰り返し処理を行っています。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?