カスタムタイムアウト実装のコルーチン

ザカリーターナー

私はasyncioを使用して、行ごとに解析し、表示された出力に基づいてさまざまなことを行う出力を出力するサブプロセスを実行しています。このプロセスにタイムアウトを設定したいのですが、プロセス全体の存続期間中はグローバルタイムアウトであってはなりません。代わりに、プロセスから特定の出力が表示された場合は常に、タイムアウトをリセットして最初からやり直したいと思います。どうすればこれを実装できますか?

グローバルタイムアウトの場合、これは機能していて簡単asyncio.wait_for(_foo(), timeout)です。単にを呼び出しますしかし、タイムアウトをリセットしてもこれを機能させることはできません。これが私がこれまでに持っているものです:

        # here invocation is my own data structure with some bookkeeping information in it
        # (such as the start time from which I want to base my timeout decisions on).
        # and process is the value returned by await asyncio.create_subprocess_exec(...)
        # _run_one_invocation() is my own function which is just a stdout readline loop
        # and some dispatching.

        # Make a Task out of the co-routine so that we decide when it gets cancelled, not Python.
        run_task = asyncio.Task(_run_one_invocation(invocation, process))
        while True:
            try:
                # Use asyncio.shield so it doesn't get cancelled if the timeout expires
                await asyncio.shield(asyncio.wait_for(run_task, 1))

                # If the await returns without raising an exception, we got to EOF and we're done.
                break
            except asyncio.TimeoutError:
                # If it's been too long since last reset, this is a "real" timeout.
                duration = time.time() - invocation.start_time
                if duration > timeout:
                    run_task.cancel()
                    raise

私はこれを実行すると、呼び出し、if文がrun_task.cancel()されていない入力されている、と私はループの先頭に戻り、呼び出しにもかかわらずときasyncio.wait_for()再びそれはすぐに上げますasyncio.CancelledError

私は何が間違っているのですか?

user4815162342

問題を修正し、コードを単純化するには、完全に回避してwait_for()(したがってshield())、wait(return_when=FIRST_COMPLETED)必要な種類のタイムアウトを実装するために使用します。

run_task = asyncio.create_task(_run_one_invocation(invocation, process))
while True:
    await asyncio.wait([run_task], timeout=1)
    if run_task.done():
        break
    if time.time() - invocation.start_time > timeout:
        run_task.cancel()
        raise asyncio.TimeoutErrror()

このアプローチの欠点は、1秒のウェイクアップが導入され、タスクが何時間も休止している場合でも、プログラム(およびその結果としてコンピューター)がスリープ状態になるのを防ぐことです。サーバーではおそらく大したことではありませんが、そのような方法はラップトップのバッテリーの消耗につながるため、回避することをお勧めします。また、1秒のスリープでは、タイムアウトの変化に反応するために最大1秒の遅延が発生します。

これを解決するには、タイムアウトを変更するコードによって発生するイベントを作成し、タイムアウトとタスクの完了に加えて、そのイベントに反応します。

timeout_changed = asyncio.Event()
# pass timeout_changed where needed, and have the code that changes
# the timeout also call timeout_changed.set()
run_task = asyncio.create_task(_run_one_invocation(invocation, process))
while True:
    remaining = timeout - (time.time() - invocation.start_time)
    timeout_changed_task = asyncio.ensure_future(timeout_changed.wait())
    await asyncio.wait([run_task, timeout_changed_task],
        return_when=asyncio.FIRST_COMPLETED, timeout=remaining)
    timeout_changed_task.cancel()
    # either: 1) the task has completed, 2) the previous timeout has
    # expired, or 3) the timeout has changed
    if run_task.done():
        break  # 1
    if time.time() - invocation.start_time > timeout:
        # 2 or 2+3
        run_task.cancel()
        raise asyncio.TimeoutErrror()
    # 3 - continue waiting with the new timeout

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Muxミドルウェアおよびカスタムコンテキスト実装でのボイラープレートの削減

分類Dev

Storyboardを使用したカスタムビューレイアウトの実装

分類Dev

woocommerceチェックアウトでカスタム支払いプラグインのカスタムjsコードを実行します

分類Dev

MKAnnotationViewコールアウトのカスタムフォント

分類Dev

インテントチューザー画面でのカスタムアイテムのコールバック

分類Dev

リストADTのパターンマッチングカスタム実装

分類Dev

ボタン付きのカスタムMKAnnotationコールアウトバブル

分類Dev

カスタムランチャーのアイコンパックをインストールする方法?

分類Dev

カスタム行レイアウトを実装するときのNullPointerException

分類Dev

FrameworkElementに基づくカスタムコントロールにマウスインタラクションを実装する

分類Dev

Javaでのカスタムクイックソートアルゴリズムの実装

分類Dev

各リサイクラービューアイテム内のボタンクリック時にテキストカウンターを実装する方法

分類Dev

React-子コンポーネントのカスタムレイアウト

分類Dev

dotnetcoreでのカスタムセッションステートストアプロバイダーの実装

分類Dev

ノックアウトのFoundationsツールチップのカスタムバインディング

分類Dev

ノックアウトのFoundationsツールチップのカスタムバインディング

分類Dev

ソフトウェアのカスタムインストールパス

分類Dev

カスタムコンポーネントのレイアウトへのアイテムの追加

分類Dev

リアルタイムチャットでのリンクの実装

分類Dev

アンドロイドのカウントとカスタムカートアイコン

分類Dev

開始時刻をカスタムでカウントダウンタイマーを実装する方法?

分類Dev

Akkaのアクターベースのカスタムイベントバスの実装がボトルネックを引き起こします

分類Dev

WTLのカスタム描画コントロールにスクロールを実装する

分類Dev

Javaカスタムコレクション実装のテストスイートはありますか?

分類Dev

衝突後のタイムアウト/クールダウンを実装する方法

分類Dev

タイムラインベースのDismissableListTileウィジェットの実装

分類Dev

カスタムコレクションビューレイアウトの作成

分類Dev

マテリアルUIカスタムテーマの実装

分類Dev

C ++クラスメソッドのタイムアウト関数テンプレートの実装

Related 関連記事

  1. 1

    Muxミドルウェアおよびカスタムコンテキスト実装でのボイラープレートの削減

  2. 2

    Storyboardを使用したカスタムビューレイアウトの実装

  3. 3

    woocommerceチェックアウトでカスタム支払いプラグインのカスタムjsコードを実行します

  4. 4

    MKAnnotationViewコールアウトのカスタムフォント

  5. 5

    インテントチューザー画面でのカスタムアイテムのコールバック

  6. 6

    リストADTのパターンマッチングカスタム実装

  7. 7

    ボタン付きのカスタムMKAnnotationコールアウトバブル

  8. 8

    カスタムランチャーのアイコンパックをインストールする方法?

  9. 9

    カスタム行レイアウトを実装するときのNullPointerException

  10. 10

    FrameworkElementに基づくカスタムコントロールにマウスインタラクションを実装する

  11. 11

    Javaでのカスタムクイックソートアルゴリズムの実装

  12. 12

    各リサイクラービューアイテム内のボタンクリック時にテキストカウンターを実装する方法

  13. 13

    React-子コンポーネントのカスタムレイアウト

  14. 14

    dotnetcoreでのカスタムセッションステートストアプロバイダーの実装

  15. 15

    ノックアウトのFoundationsツールチップのカスタムバインディング

  16. 16

    ノックアウトのFoundationsツールチップのカスタムバインディング

  17. 17

    ソフトウェアのカスタムインストールパス

  18. 18

    カスタムコンポーネントのレイアウトへのアイテムの追加

  19. 19

    リアルタイムチャットでのリンクの実装

  20. 20

    アンドロイドのカウントとカスタムカートアイコン

  21. 21

    開始時刻をカスタムでカウントダウンタイマーを実装する方法?

  22. 22

    Akkaのアクターベースのカスタムイベントバスの実装がボトルネックを引き起こします

  23. 23

    WTLのカスタム描画コントロールにスクロールを実装する

  24. 24

    Javaカスタムコレクション実装のテストスイートはありますか?

  25. 25

    衝突後のタイムアウト/クールダウンを実装する方法

  26. 26

    タイムラインベースのDismissableListTileウィジェットの実装

  27. 27

    カスタムコレクションビューレイアウトの作成

  28. 28

    マテリアルUIカスタムテーマの実装

  29. 29

    C ++クラスメソッドのタイムアウト関数テンプレートの実装

ホットタグ

アーカイブ