Wait¶
awaitableオブジェクト(Taskやコルーチン)はさまざまな条件で待機できる
タイムアウトを設定できる
例外に応じて処理を制御できる
- タイムアウト
- 要素の終了待機
Future¶
非同期処理の最終結果を表現する特別な低レベルのawaitableオブジェクト
pending
finished
cancelled
コルーチンはFutureの結果が返されるか例外が送出されるまでawaitされる
asyncio.wait_for¶
awaitableオブジェクトが完了するかタイムアウトになるのを待つ
awaitableオブジェクトがコルーチンだった場合はTaskとしてスケジュールされる
タイムアウトの場合はTaskをキャンセルし、 asyncio.TimeoutError を送出する
1import asyncio
2import time
3
4
5async def main():
6 await asyncio.wait_for(asyncio.sleep(3), timeout=1)
7
8
9start = time.time()
10asyncio.run(main())
11print(f"time: {time.time() - start}")
asyncio.TimeoutError
になる
asyncio.as_completed¶
awaitableオブジェクトを同時に実行する
完了した順に、イテレータを返す
イテレーションが完了する前にタイムアウトした場合は
asyncio.TimeoutError
を送出する
1import asyncio
2import time
3
4
5async def neru(n):
6 await asyncio.sleep(n)
7 return n
8
9
10async def main():
11 for f in asyncio.as_completed([neru(2), neru(4), neru(1)], timeout=3):
12 result = await f
13 print(f"{result=}")
14
15
16start = time.time()
17asyncio.run(main())
18print(f"time: {time.time() - start}")
result=1
result=2
Traceback (most recent call last):
File "/home/driller/repo/events/20210912/docs/source/code/as_completed.py", line 17, in <module>
asyncio.run(main())
File "/usr/local/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/home/driller/repo/events/20210912/docs/source/code/as_completed.py", line 12, in main
result = await f
File "/usr/local/lib/python3.9/asyncio/tasks.py", line 613, in _wait_for_one
raise exceptions.TimeoutError
asyncio.exceptions.TimeoutError
asyncio.wait¶
awaitableオブジェクトを同時に実行する
完了したタスクと保留中のタスクのset(集合)を返す
return_when
でいつ結果を返すかを指定する
1import asyncio
2import time
3
4
5async def main():
6 tasks = [
7 asyncio.create_task(asyncio.sleep(1)),
8 asyncio.create_task(asyncio.sleep(3)),
9 ]
10 done, pending = await asyncio.wait(tasks, timeout=2)
11
12 for t in tasks:
13 print(f"{t} in done: {t in done}")
14 print(f"{t} in pending: {t in pending}")
15
16
17start = time.time()
18asyncio.run(main())
19print(f"time: {time.time() - start}")
<Task finished name='Task-2' coro=<sleep() done, defined at /usr/local/lib/python3.9/asyncio/tasks.py:636> result=None> in done: True
<Task finished name='Task-2' coro=<sleep() done, defined at /usr/local/lib/python3.9/asyncio/tasks.py:636> result=None> in pending: False
<Task pending name='Task-3' coro=<sleep() running at /usr/local/lib/python3.9/asyncio/tasks.py:654> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f0123edb2b0>()]>> in done: False
<Task pending name='Task-3' coro=<sleep() running at /usr/local/lib/python3.9/asyncio/tasks.py:654> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f0123edb2b0>()]>> in pending: True
time: 2.0029919147491455
return_when¶
asyncio.waitがいつ返すかを指定
- FIRST_COMPLETED
いずれかのFutureが終了したかキャンセルされたときに返す
- FIRST_EXCEPTION
いずれかのFutureが例外の送出で終了した場合に返す
例外を送出したFutureがない場合は、
ALL_COMPLETED
と等価になる
- ALL_COMPLETED
すべてのFutureが終了したかキャンセルされたときに返す(デフォルト)
1import asyncio
2import time
3from asyncio.tasks import FIRST_COMPLETED
4
5
6async def main():
7 tasks = [
8 asyncio.create_task(asyncio.sleep(1)),
9 asyncio.create_task(asyncio.sleep(3)),
10 ]
11 done, pending = await asyncio.wait(tasks, timeout=2, return_when=FIRST_COMPLETED)
12
13 for t in tasks:
14 print(f"{t} in done: {t in done}")
15 print(f"{t} in pending: {t in pending}")
16
17
18start = time.time()
19asyncio.run(main())
20print(f"time: {time.time() - start}")
<Task finished name='Task-2' coro=<sleep() done, defined at /usr/local/lib/python3.9/asyncio/tasks.py:636> result=None> in done: True
<Task finished name='Task-2' coro=<sleep() done, defined at /usr/local/lib/python3.9/asyncio/tasks.py:636> result=None> in pending: False
<Task pending name='Task-3' coro=<sleep() running at /usr/local/lib/python3.9/asyncio/tasks.py:654> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fe15a347400>()]>> in done: False
<Task pending name='Task-3' coro=<sleep() running at /usr/local/lib/python3.9/asyncio/tasks.py:654> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fe15a347400>()]>> in pending: True
time: 1.0022432804107666
練習問題¶
asyncio.as_completed
に複数のコルーチンを渡し、うち1つのコルーチンは例外を送出してください1.の例外をtry-except処理してください