Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Timeout decorator

with 2 comments

Декоратор який використовуючи сигнал Unix SIGALRM перериває роботу функції якщо та працює довше ніж задане число секунд:

import signal

class TimeOut(Exception):
    def __init__(self, msg='Time out error'):
        super(Exception, self).__init__(msg)

def on_alarm(signum, frame): # при надходженні сигналу кидати виняток
    raise TimeOut()

def limit_time(t, default=None):
    signal.signal(signal.SIGALRM, on_alarm) # встановити обробник сигналу

    def decorator(f): 
        def decorated(*args, **kwargs):
            signal.alarm(t) # попросити ОС прислати нам сигнал через t секунд
            try:
                return f(*args, **kwargs)
            except TimeOut:
                return default
        return decorated
    return decorator

import contextlib
# Дякую Алекс!
@contextlib.contextmanager
def time_limit(t):
    signal.signal(signal.SIGALRM, on_alarm)
    signal.alarm(t)
    try:
        yield
    except TimeOut:
        pass


import time

@limit_time(5) # працювати не довше 5 секунд
def test():
    for i in range(10):
        print i
        time.sleep(1)

test()

with time_limit(5):
    for i in range(10):
        print i
        time.sleep()

Advertisements

Written by bunyk

Вересень 2, 2014 at 14:13

Оприлюднено в Кодерство

Tagged with ,

Відповідей: 2

Subscribe to comments with RSS.

  1. Здається, там на line 17 повинно бути `return f`

    Можна ще так:

    import contextlib

    @contextlib.contextmanager
    def time_limit(t):
    signal.signal(signal.SIGALRM, on_alarm) # встановити обробник сигналу
    signal.alarm(t)
    try:
    yield
    except TimeOut:
    pass

    data = None
    with time_limit(5):
    data = test()

    Alexander Shchapov

    Вересень 2, 2014 at 15:20

    • Так, забув про дані що повертаються.

      І так, спосіб з контекст-менеджером ще крутіший, бо можна будь-який код обмежувати, а не лише функції. Дякую.

      bunyk

      Вересень 6, 2014 at 02:34


Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: