5.1 イベントループ (Event Loop)
さて、非同期処理の第二の部分、つまりイベントループ (Event Loop)
、タスク (Task)
、そしてFuture
について簡単に触れておこう。
イベントループをオーケストラの指揮者、タスクを音楽家、Futureを楽譜として考えてみてください。指揮者 (Event Loop) は音楽家 (Task) の作業を調整し、楽譜 (Future) を読みながら音楽 (非同期操作) を演奏します。
イベントループ (Event Loop)
は
Pythonでの非同期プログラミングの基盤です。これは非同期タスクの実行、イベントの管理、入出力の処理を担当しています。イベントループは、新しいイベントやタスクの存在を常にチェックし、それらが準備できたら実行します。
主な機能
-
run_forever()
: イベントループを開始し、stop()
が呼び出されるまで実行を続けます。 -
run_until_complete(future)
: 指定したFutureオブジェクトやコルーチンが完了するまでイベントループを実行します。 stop()
: イベントループを停止します。-
create_task(coroutine)
: コルーチンをタスクとして実行予定にします。
使用例:
import asyncio
async def hello():
print("Hello, world!")
await asyncio.sleep(1)
print("Hello again!")
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()
この例では、まずメソッドget_event_loop()
を使用してasyncio
ライブラリの現在のEventLoop
オブジェクトを取得します。
次に、このEventLoop
にコルーチンhello
を追加し、run_until_complete()
メソッドを使用して実行するように要求します。
最後のステップで、close()
メソッドを使用してEventLoop
を閉じます。
このコードを実行すると、まず "Hello, world!" が表示され、その後1秒間待ってから "Hello again!" が表示されるのを確認できます。これは、イベントループが非同期関数の実行をどのように管理しているかを示しています。
これらの操作については、次の講義で詳しく説明します。
5.2 Tasks
タスク (Tasks)
は、コルーチンの実行を管理し、その状態を追跡するためのラッパーです。タスクを使うと、イベントループを通じてコルーチンを並行して実行し、それらを管理できます。
タスクの作成と管理
-
asyncio.create_task(coroutine)
: コルーチンを実行するためにタスクを作成します。 -
Task.result()
: 完了したタスクの結果を返すか、エラーで終了した場合は例外を発生させます。 Task.cancel()
: タスクの実行をキャンセルします。
使用例:
import asyncio
async def say_hello():
await asyncio.sleep(1)
print("Hello")
async def main():
task = asyncio.create_task(say_hello())
await task
asyncio.run(main())
この例では、コルーチンsay_hello()
をTask
オブジェクトでラップしています。これも非同期オブジェクトなので、その結果を得るにはawait
演算子を適用する必要があります。
このコードを実行すると、1秒待ってから "Hello" が表示されます。これは、Taskがコルーチンの実行を管理し、awaitを使ってその完了を待つ方法を示しています。
Taskの使い方については、次の講義で詳しく説明します。
5.3 Futures
Futureオブジェクト は、将来利用可能になる非同期操作の結果を表します。これらは、非同期操作の状態を管理し、結果や例外を設定することを可能にします。
主なメソッド:
-
set_result(result)
:Future
オブジェクトに結果を設定します。 -
set_exception(exception)
:Future
オブジェクトに例外を設定します。 -
result()
:Future
オブジェクトの結果を返すか、エラーで終了した場合は例外を発生させます。 -
exception()
: 例外が設定されている場合にそれを返します。
使用例:
import asyncio
async def set_future(fut, value):
await asyncio.sleep(1)
fut.set_result(value)
async def main():
loop = asyncio.get_running_loop()
fut = loop.create_future()
await set_future(fut, 'Hello, future!')
print(fut.result())
asyncio.run(main())
この例では、Futureを作成し、1秒後にその値を設定し、その後結果を出力します。プログラムは1秒間待ってから 'Hello, future!' を出力します。これは、Futureが将来利用可能になる結果を表現する方法を示しています。
Task
オブジェクトとは異なり、Future
オブジェクトは特定のEvent Loop
に関連付けられており、実行中の非同期関数はその結果を設定できます。ただし、通常これは少し異なる方法で動作します。
通常、Future
オブジェクトは、非同期操作の高レベルな管理を提供するタスクTask
と組み合わせて使用されます。
Event Loop
、Task
、およびFuture
に慣れたところで、次の講義でそれらについてさらに詳しく見ていきましょう。
GO TO FULL VERSION