簡體   English   中英

多處理函數上的超時裝飾器

[英]Time out decorator on a multprocessing function

我有這個裝飾器直接取自我在網上找到的一個例子:

class TimedOutExc(Exception):
    pass


def timeout(timeout):
    def decorate(f):
        def handler(signum, frame):
            raise TimedOutExc()

        def new_f(*args, **kwargs):

            old = signal.signal(signal.SIGALRM, handler)
            signal.alarm(timeout)

            try:
                result = f(*args, **kwargs)
            except TimedOutExc:
                return None
            finally:
                signal.signal(signal.SIGALRM, old)
            signal.alarm(0)
            return result

        new_f.func_name = f.func_name
        return new_f

    return decorate

如果 f 函數超時,它會拋出異常。

嗯,它可以工作,但是當我在多處理函數上使用這個裝飾器並由於超時而停止時,它不會終止計算中涉及的進程。 我怎樣才能做到這一點?

我不想啟動異常並停止程序。 基本上我想要的是當 f 超時時,讓它返回 None 然后終止所涉及的進程。

雖然我同意 Aaron 回答的要點,但我想詳細說明一下。

multiprocessing啟動的進程必須在要裝飾的函數中停止; 我不認為這可以簡單地從裝飾器本身完成(裝飾函數是唯一知道它啟動了什么計算的實體)。

除了讓裝飾函數捕獲SIGALARM ,您還可以捕獲自定義TimedOutExc異常——這可能更靈活。 您的示例將變為:

import signal
import functools

class TimedOutExc(Exception):
    """
    Raised when a timeout happens
    """

def timeout(timeout):
    """
    Return a decorator that raises a TimedOutExc exception
    after timeout seconds, if the decorated function did not return.
    """

    def decorate(f):

        def handler(signum, frame):
            raise TimedOutExc()

        @functools.wraps(f)  # Preserves the documentation, name, etc.
        def new_f(*args, **kwargs):

            old_handler = signal.signal(signal.SIGALRM, handler)
            signal.alarm(timeout)

            result = f(*args, **kwargs)  # f() always returns, in this scheme

            signal.signal(signal.SIGALRM, old_handler)  # Old signal handler is restored
            signal.alarm(0)  # Alarm removed

            return result

        return new_f

    return decorate

@timeout(10)
def function_that_takes_a_long_time():
    try:
        # ... long, parallel calculation ...
    except TimedOutExc:
        # ... Code that shuts down the processes ...
        # ...
        return None  # Or exception raised, which means that the calculation is not complete

我懷疑這可以用裝飾器來完成:裝飾器是一個函數的包裝器; 該函數是一個黑匣子。 裝飾器和它包裝的函數之間沒有通信。

您需要做的是重寫您的函數代碼以使用SIGALRM處理程序終止它已啟動的任何進程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM