Бывают ситуации, когда надо ограничить время выполнения скрипта. К примеру, в программе есть запрос к удалённому серверу, который может длиться сколь угодно долго. В таком случае надо сделать прерывание выполнения функции при длительном простое. В этой статье рассмотрю простейший способ создания такого прерывания.
Рабочая среда: Linux Mint + Python (версия 2.7.12).
Программист: я — непрофессионал в Python. За всю жизнь написал на нём меньше тысячи строк кода. Поэтому формулировки могут быть неточными. Изучать Python не хочу, потому что использую его для очень простых задач.
Методы: Реализуем прерывание через библиотеку «signal». Потому что это самый простой способ.
Прерывание выполнения скрипта по времени
Возьмём простую тестовую программу:
#!/usr/bin/python -i
import time
try:
time.sleep(5)
except Exception as e:
print e
Здесь time.sleep(5) — это пятисекундная задержка. Она будет выполнять роль функции, которая может исполняться очень долго. И нам необходимо ограничить время её выполнения — прервать через 2 секунды.
Воспользуемся библиотекой «signal«. Signal представляет собой таймер, который будет считаться в фоновом режиме, параллельно с программой. На работу Signal не влияет ничего, в том числе задержка через time.sleep(5). Signal сработает (выдаст Exception) в любом случае, как только таймер отсчитает нужное количество секунд.
Синтаксис команды прост:
signal.alarm(N) — запускает таймер сигнала на N секунд
signal.alarm(0) — останавливает таймер.
Вставим signal в пример:
#!/usr/bin/python -i
import signal
import time
try:
signal.alarm(2)
time.sleep(5)
signal.alarm(0)
except Exception as e:
print e
Посмотрим внимательнее на скрипт. Сначала запускается двухсекундный отсчёт signal.alarm(2), затем пятисекундная задержка time.sleep(5). В конце выполняется команда signal.alarm(0), которая останавливает отсчёт до срабатывания сигнала.
Как можно догадаться, с таким скриптом Exception всегда будет срабатывать. Потому что задержка в 5 секунд выполняется дольше, чем время ожидания сигнала в 2 секунды.
Попробуйте изменить время сна с time.sleep(5) на time.sleep(1). И Exception не будет происходить.
Специфический ответ от signal
В приведённом примере во время вызова Exception в переменной «e» будет находиться текст «Сигнал таймера». Это не информативно. Но есть способ задать этот текст:
#!/usr/bin/python -i
import signal
import time
def signal_handler(signum, frame):
raise Exception(«Script is too slow!«)
signal.signal(signal.SIGALRM, signal_handler)
try:
signal.alarm(2)
time.sleep(5)
signal.alarm(0)
except Exception as e:
print e
Теперь во время прерывания будет печататься текст «Script is too slow!«.
Заключение
Если вам понадобится ограничить время работы python скрипта, то легче всего это можно сделать через «signal» библиотеку.
P.S.
Можно сделать через библиотеку thread, но там больше заморочек…