timeoutデコレータはPythonにおいて、関数の実行時間を制限するために使用されます。関数が指定された時間よりも長く実行された場合、TimeoutExceptionを発生させます。これは、関数が無限にハングしないように保証したい場合に特に便利です。

ソースコード

import signal

class TimeoutException(Exception):
    pass

def timeout(seconds):
    def decorator(func):
        def handler(signum, frame):
            raise TimeoutException(f"Function {func.__name__} timed out after {seconds} seconds")

        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, handler)
            signal.alarm(seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                signal.alarm(0)
            return result

        return wrapper
    return decorator

@timeout(5)
def long_running_function():
    import time
    time.sleep(10)

try:
    long_running_function()
except TimeoutException as e:
    print(e)  # Output: Function long_running_function timed out after 5 seconds

 

解説

  1. シグナル処理: signalモジュールを使用して、指定された時間後にトリガーされるアラームシグナルを設定します。

     
  2. TimeoutException: 関数が割り当てられた時間を超過すると、カスタム例外が発生します。

     
  3. デコレータ構造: timeoutデコレータは対象関数をラップし、signalを使用してタイミングロジックを管理します。

 

ユースケース

  • ネットワークリクエスト: ネットワーク応答を待つ時間に制限を設定します。
     
  • 長時間計算: 計算コストの高い関数が無限に実行されるのを防ぎます。
     
  • リソース管理: 制限されたリソースにアクセスする関数がそれらを独占的に使用しないようにします。

 

制限事項

  • プラットフォーム依存性: signalモジュールはUnixベースのシステムでのみ動作します。=>それを回避するには、Sentryなど、エラーを通知するいくつかの公開サービスを使用できます。

     
  • スレッド安全性: シグナルはプロセス全体であるため、マルチスレッドアプリケーションには適していません。

timeoutデコレータを組み込むことで、プログラムをより堅牢にし、長時間実行される関数による潜在的なハングアップを防ぐことができます。