await、タスク、ギャザリング
並行処理に await、asyncio.create_task、asyncio.gather を使います。
「await、タスク、ギャザリング」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。
awaitと逐次実行の比較
awaitだけを使うと、コルーチンは逐次実行されます。並行して実行するには、Taskでラップしてください。
import asyncio
async def main():
# Sequential — total ~3 s
await asyncio.sleep(2)
await asyncio.sleep(1)
# Concurrent using gather — total ~2 s
await asyncio.gather(asyncio.sleep(2), asyncio.sleep(1))asyncio.create_task()
asyncio.create_task(coro)は、コルーチンを現在のコルーチンと並行して独立したTaskとして実行するようスケジュールします。
import asyncio
async def work(n):
await asyncio.sleep(n)
return n
async def main():
t1 = asyncio.create_task(work(2))
t2 = asyncio.create_task(work(1))
r1 = await t1
r2 = await t2
print(r1, r2) # 2 1 (total ~2 s)
asyncio.run(main())asyncio.gather()
asyncio.gather(*coros)はコルーチンを並行して実行し、すべてが完了すると結果を順序どおりに返します。
import asyncio
async def fetch(i):
await asyncio.sleep(1)
return f"data-{i}"
async def main():
results = await asyncio.gather(fetch(1), fetch(2), fetch(3))
print(results) # ["data-1", "data-2", "data-3"] in ~1 s
asyncio.run(main())return_exceptionsを指定したgather
return_exceptions=Trueを設定すると、失敗したコルーチンは例外を結果として返します。そのため、gather全体がキャンセルされることを防げます。
import asyncio
async def risky(n):
if n == 2: raise ValueError("bad")
return n
async def main():
results = await asyncio.gather(
risky(1), risky(2), risky(3),
return_exceptions=True
)
print(results) # [1, ValueError("bad"), 3]asyncio.wait()
asyncio.wait(tasks, return_when=...)は、doneとpendingという2つの集合を返します。最初の結果に反応するにはFIRST_COMPLETEDを使用します。
import asyncio
async def slow(): await asyncio.sleep(3); return "slow"
async def fast(): await asyncio.sleep(1); return "fast"
async def main():
tasks = {asyncio.create_task(slow()), asyncio.create_task(fast())}
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
for t in pending: t.cancel()タスクのキャンセル
キャンセルを要求するにはtask.cancel()を呼び出します。タスクは次のawait地点でasyncio.CancelledErrorを受け取ります。
import asyncio
async def long_job():
try:
await asyncio.sleep(100)
except asyncio.CancelledError:
print("Cancelled!")
raise # re-raise is required
async def main():
t = asyncio.create_task(long_job())
await asyncio.sleep(1)
t.cancel()
await tasyncio.timeout() — Python 3.11以降
asyncio.timeout(seconds)でawaitを囲むと、処理に時間がかかりすぎた場合にキャンセルできます。
import asyncio
async def main():
try:
async with asyncio.timeout(2):
await asyncio.sleep(10) # too slow
except TimeoutError:
print("Timed out!")asyncio.wait_for()
Python 3.11未満では、asyncio.wait_for(coro, timeout=N)を使用してタイムアウトを追加します。タイムアウトになるとasyncio.TimeoutErrorが発生します。
import asyncio
async def slow(): await asyncio.sleep(5)
async def main():
try:
await asyncio.wait_for(slow(), timeout=2)
except asyncio.TimeoutError:
print("Timed out")タスクの名前付けと検査
asyncio.create_task(coro, name="...")を使用してタスクに名前を付けると、デバッグしやすくなります。名前はtask.get_name()で確認できます。
import asyncio
async def worker(): await asyncio.sleep(1)
async def main():
t = asyncio.create_task(worker(), name="worker-1")
print(t.get_name()) # worker-1
await tTaskGroup — Python 3.11以降
asyncio.TaskGroupは、タスクを構造化されたグループとして作成します。いずれかのタスクで例外が発生すると、すべてのタスクがキャンセルされます。
import asyncio
async def main():
async with asyncio.TaskGroup() as tg:
t1 = tg.create_task(asyncio.sleep(1))
t2 = tg.create_task(asyncio.sleep(2))
# all tasks done hereレート制限のためのセマフォ
asyncio.Semaphore(n)を使用すると、同時に実行できる処理の数(API呼び出しなど)を制限できます。
import asyncio
sem = asyncio.Semaphore(5) # max 5 concurrent
async def limited_fetch(url):
async with sem:
await fetch(url) # at most 5 at a time確認問題
await coro()とasyncio.create_task(coro())の違いは何ですか。
まとめ
並行実行にはcreate_taskまたはgatherを使用します。gatherはすべての結果を収集し、waitはきめ細かな制御を可能にします。タスクは.cancel()でキャンセルし、wait_forまたはasyncio.timeoutでタイムアウトを設定します。
よくある質問
「await、タスク、ギャザリング」レッスンは無料ですか?
はい。「await、タスク、ギャザリング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。
「await、タスク、ギャザリング」で何を学びますか?
並行処理に await、asyncio.create_task、asyncio.gather を使います。 ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Python Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「await、タスク、ギャザリング」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPython Academyレッスンでコードを書いて実行できますか?
はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- コルーチンとイベントループ
- await、タスク、ギャザリング
- 非同期コンテキストマネージャーとイテレーター
- 本番環境での非同期 I/O パターン