1
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?

More than 1 year has passed since last update.

trioによる並行処理③(move_on_after, move_on_at)

Last updated at Posted at 2022-09-28

目次

trioにある便利な関数move_on_after()move_on_at()を紹介します。

move_on_after

with move_on_after(秒数)のようにしてwithブロックを作ることができ、指定した秒数経つとブロックを抜けます。例えば

import trio

async def main():
    start_time = trio.current_time()
    with trio.move_on_after(3):
        while True:
            elapsed_time = trio.current_time() - start_time
            print(f"elapsed_time={elapsed_time:.1f}")
            await trio.sleep(1)
    elapsed_time = trio.current_time() - start_time
    print(f"done (elapsed_time={elapsed_time:.1f})")

trio.run(main)
結果
elapsed_time=0.0
elapsed_time=1.0
elapsed_time=2.0
done (elapsed_time=3.0)
  • trio.current_time()は現在の時間を秒単位で取得する関数です
  • while Trueのループは中でawait trio.sleep(1)を使っているため1秒周期で回る無限ループです
    • 無限ループですがwith trio.move_on_after(3)のブロック内にあるため3秒経ったら抜けます
    • 抜けるのはawaitで非同期関数が呼ばれたタイミングです(ここではawait trio.sleep(1)

尚、timeoutで抜けたかどうかはmove_on_after()の返り値のCancelScopeのcancelled_caughtで分かります。
timeoutで抜けた場合はTrueとなります。例えば

import trio

async def main():
    with trio.move_on_after(3) as cancel_scope:
        for _ in range(5):
            await trio.sleep(1)
    print(f"cancelled_caught={cancel_scope.cancelled_caught}")

trio.run(main)
実行結果
cancelled_caught=True

ここでmove_on_after()の引数を6にするとタイムアウトで抜けなくなり、実行結果はcancelled_caught=Falseとなります。

move_on_at

with move_on_at(秒数)のようにwithブロックを作ることができます。
move_on_after()はtimeoutまでの秒数を指定する関数でしたが、move_on_at()はtimeoutの時刻を指定します。例えば

import trio

async def main():
    start_time = trio.current_time()
    deadline = start_time + 3
    with trio.move_on_at(deadline):
        while True:
            elapsed_time = trio.current_time() - start_time
            print(f"elapsed_time={elapsed_time:.1f}")
            await trio.sleep(1)
    elapsed_time = trio.current_time() - start_time
    print(f"done (elapsed_time={elapsed_time:.1f})")

trio.run(main)
結果
elapsed_time=0.0
elapsed_time=1.0
elapsed_time=2.0
done (elapsed_time=3.0)

尚、timeoutの時刻(deadline)は動的に変えることができます。
move_on_at()の返り値のCancelScopeのdeadlineを更新すればよいです。
上の例のtimeoutを3秒ではなく5秒に変更してみます。

import trio

async def main():
    start_time = trio.current_time()
    deadline = start_time + 3
    with trio.move_on_at(deadline) as cancel_scope:
        cancel_scope.deadline = start_time + 5
        while True:
            elapsed_time = trio.current_time() - start_time
            print(f"elapsed_time={elapsed_time:.1f}")
            await trio.sleep(1)
    elapsed_time = trio.current_time() - start_time
    print(f"done (elapsed_time={elapsed_time:.1f})")

trio.run(main)
結果
elapsed_time=0.0
elapsed_time=1.0
elapsed_time=2.0
elapsed_time=3.0
elapsed_time=4.0
done (elapsed_time=5.0)

また、move_on_after()と同様にCancelScope.cancelled_caughtで、timeoutしたかどうかが分かります。

1
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
1
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?