はじめに¶
動作要件¶
- Python 3.10 以降(CPython または PyPy)
- サードパーティ依存なし
インストール¶
Warning
PyPI にはまだ公開されていません。GitHub からインストールしてください。
uv を使う場合:
はじめての AsyncValue¶
AsyncValue は初期値をラップします。読み書きは
value プロパティを通して、ふつうの属性と同じように行います。
from asyncio_util import AsyncValue
score = AsyncValue(0)
print(score.value) # 0
score.value = 10
print(score.value) # 10
ふつうの属性との違いは、他のタスクが await できることです。
import asyncio
from asyncio_util import AsyncValue
score = AsyncValue(0)
async def announcer():
value = await score.wait_value(lambda v: v >= 100)
print(f"{value} に到達!")
async def game():
for points in (30, 40, 50):
await asyncio.sleep(0.1)
score.value += points # プロパティは累算代入にも対応
async def main():
await asyncio.gather(announcer(), game())
asyncio.run(main())
出力:
ここにポーリングはありません。announcer() は score.value += points の代入で
述語が真になるまで眠っていて、条件を満たしたまさにその値を受け取ります。
値と述語¶
待機系の API はすべて、ふつうの値(== で比較)と述語関数の
どちらでも受け付けます。
await score.wait_value(100) # value == 100
await score.wait_value(lambda v: v >= 100) # predicate(value) が True
None を待つ
None も他の値と同じように扱われます。
await av.wait_value(None) は値が None になるまで待ちます。
タイムアウト¶
wait_value() と wait_transition() は timeout 引数を受け取り、期限切れで
asyncio.TimeoutError を送出します。
標準ライブラリのイディオムとの組み合わせも同様に機能します。コードベースの 流儀に合わせてください。
await asyncio.wait_for(score.wait_value(100), timeout=1.0) # 3.10+
async with asyncio.timeout(1.0): # 3.11+
await score.wait_value(100)
タイムアウトなどで待機がキャンセルされた場合、内部のウェイターは即座に 片付けられます。リークはありません。
等値性について¶
現在の値と等しい(==)値の代入は何もしません。ウェイターは起きず、
遷移としても記録されません。この重複排除があるおかげで、派生値
(派生と合成を参照)を低コストに保てます。
スレッド安全性¶
AsyncValue はスレッドセーフではありません。value への代入は
イベントループが動いているスレッドからのみ行ってください。別スレッドからは、
まずループに乗せます。
次のステップ¶
- 値を待つ —
wait_value・wait_transition・held_forの 詳細。 - 変化をイテレートする — 値をストリームとして消費する。
- 派生と合成 — 値から値を組み立てる。
- タスクとキャンセル —
AsyncValue以外の構造化ヘルパー。 - イベント・ストリーム・タイミング — 残りのツール群。