Содержание страницы
17.4. signal – Установка обработчиков для асинхронных событий¶signal – Set handlers for asynchronous events
Этот модуль предоставляет механизмы для использования обработчиков сигналов в Python. Несколько общих правил работы с сигналами и их обработчиками:
Обработчик конкретного сигнала после установки остается активным до явной переустановки (Python эмулирует интерфейс в стиле BSD независимо от реализации), за исключением обработчика для
SIGCHLD, который следует базовой реализации.Нет способа временно «блокировать» сигналы в критических секциях (поскольку это поддерживается не во всех разновидностях Unix).
Хотя с точки зрения пользователя Python обработчики сигналов вызываются асинхронно, они могут возникнуть только между «атомарными» инструкциями интерпретатора Python. Это означает, что сигналы, поступающие во время длительных вычислений, реализованных чисто на C (например, при сопоставлении регулярных выражений с большими объёмами текста), могут быть задержаны на произвольное время.
Когда сигнал поступает во время операции ввода-вывода, возможно, что после возврата из обработчика сигнала операция ввода-вывода возбудит исключение. Это зависит от семантики прерывания системных вызовов в конкретной Unix-системе.
Поскольку обработчик сигналов на C всегда возвращает управление, нет смысла перехватывать синхронные ошибки, такие как
SIGFPEилиSIGSEGV.Python по умолчанию устанавливает небольшое количество обработчиков сигналов:
SIGPIPEигнорируется (поэтому ошибки записи в каналы и сокеты могут сообщаться как обычные исключения Python), аSIGINTпреобразуется в исключениеKeyboardInterrupt. Все они могут быть переопределены.Следует соблюдать осторожность, если в одной программе используются и сигналы, и потоки. Основное правило при одновременном использовании сигналов и потоков: всегда выполняйте операции
signal()в главном потоке выполнения. Любой поток может выполнитьalarm(),getsignal(),pause(),setitimer()илиgetitimer(); только главный поток может установить новый обработчик сигнала, и только главный поток будет получать сигналы (это обеспечивается модулемsignalPython, даже если базовая реализация потоков поддерживает отправку сигналов отдельным потокам). Это означает, что сигналы нельзя использовать как средство межпотокового взаимодействия. Вместо этого используйте блокировки.
Переменные, определенные в модуле signal:
-
signal.SIG_DFL¶ Это один из двух стандартных вариантов обработки сигналов; он просто выполняет функцию по умолчанию для сигнала. Например, на большинстве систем действие по умолчанию для
SIGQUIT– сбросить дамп ядра и завершиться, тогда как действие по умолчанию дляSIGCHLD– просто игнорировать его.
-
signal.SIG_IGN¶ Это еще один стандартный обработчик сигнала, который просто игнорирует данный сигнал.
-
SIG* Все номера сигналов определены символически. Например, сигнал разъединения (hangup) определяется как
signal.SIGHUP; имена переменных совпадают с именами, используемыми в программах на C, которые можно найти в<signal.h>. Страница руководства Unix для «signal()» перечисляет существующие сигналы (в некоторых системах это signal(2), в других список находится в signal(7)). Обратите внимание, что не все системы определяют один и тот же набор имен сигналов; модуль определяет только те имена, которые определены системой.
-
signal.CTRL_C_EVENT¶ Сигнал, соответствующий нажатию клавиши Ctrl+C. Этот сигнал можно использовать только с
os.kill().Доступность: Windows.
Новое в версии 2.7.
-
signal.CTRL_BREAK_EVENT¶ Сигнал, соответствующий нажатию клавиши Ctrl+Break. Этот сигнал можно использовать только с
os.kill().Доступность: Windows.
Новое в версии 2.7.
-
signal.NSIG¶ На единицу больше номера самого высокого сигнала.
-
signal.ITIMER_REAL¶ Уменьшает интервальный таймер в реальном времени и доставляет
SIGALRMпо истечении.
-
signal.ITIMER_VIRTUAL¶ Уменьшает интервальный таймер только во время выполнения процесса и отправляет SIGVTALRM по истечении.
-
signal.ITIMER_PROF¶ Уменьшает интервальный таймер как при выполнении процесса, так и при выполнении системой от имени процесса. В паре с ITIMER_VIRTUAL этот таймер обычно используется для профилирования времени, затраченного приложением в пользовательском и ядерном пространстве. SIGPROF доставляется по истечении времени.
Модуль signal определяет одно исключение:
-
exception
signal.ItimerError¶ Возбуждается для указания на ошибку в реализации
setitimer()илиgetitimer(). Этого исключения следует ожидать, если некорректный интервальный таймер или отрицательное время передаются вsetitimer(). Это исключение является подтипомIOError.
Модуль signal определяет следующие функции:
-
signal.alarm(time)¶ Если time не равно нулю, эта функция запрашивает отправку сигнала
SIGALRMпроцессу через time секунд. Любая ранее запланированная тревога отменяется (одновременно может быть запланирована только одна тревога). Возвращаемое значение – количество секунд до момента, когда должна была быть доставлена предыдущая тревога. Если time равно нулю, тревога не планируется, а любая запланированная отменяется. Если возвращаемое значение равно нулю, текущая тревога не запланирована. (См. страницу руководства Unix alarm(2).) Доступность: Unix.
-
signal.getsignal(signalnum)¶ Возвращает текущий обработчик сигнала signalnum. Возвращаемое значение может быть вызываемым объектом Python или одним из специальных значений
signal.SIG_IGN,signal.SIG_DFLилиNone. Здесьsignal.SIG_IGNозначает, что сигнал ранее игнорировался,signal.SIG_DFLозначает, что ранее использовался способ обработки сигнала по умолчанию, аNoneозначает, что предыдущий обработчик сигнала не был установлен из Python.
-
signal.pause()¶ Заставляет процесс спать до получения сигнала; затем будет вызван соответствующий обработчик. Ничего не возвращает. Недоступно в Windows. (См. страницу руководства Unix signal(2).)
-
signal.setitimer(which, seconds[, interval])¶ Устанавливает заданный интервальный таймер (один из
signal.ITIMER_REAL,signal.ITIMER_VIRTUALилиsignal.ITIMER_PROF), указанный через which, для срабатывания через seconds секунд (допускается число с плавающей точкой, в отличие отalarm()) и затем каждые interval секунд. Интервальный таймер, указанный через which, можно сбросить, установив seconds в ноль.Когда срабатывает интервальный таймер, процессу отправляется сигнал. Отправляемый сигнал зависит от используемого таймера:
signal.ITIMER_REALдоставляетSIGALRM,signal.ITIMER_VIRTUALотправляетSIGVTALRM, аsignal.ITIMER_PROFдоставляетSIGPROF.Старые значения возвращаются в виде кортежа: (delay, interval).
Попытка передать недопустимый интервальный таймер вызовет
ItimerError. Доступность: Unix.Новое в версии 2.6.
-
signal.getitimer(which)¶ Возвращает текущее значение указанного интервального таймера, заданного через which. Доступность: Unix.
Новое в версии 2.6.
-
signal.set_wakeup_fd(fd)¶ Устанавливает fd пробуждения в fd. Когда получен сигнал, в fd записывается один
'\0'байт. Это может использоваться библиотекой для пробуждения вызова poll или select, чтобы сигнал был полностью обработан.Возвращается старый fd пробуждения (или -1, если пробуждение через файловый дескриптор не было включено). Если fd равен -1, пробуждение через файловый дескриптор отключается. Если не -1, то fd должен быть неблокирующим. Задача библиотеки – удалить все байты из fd перед повторным вызовом poll или select.
Когда потоки включены, эту функцию можно вызывать только из главного потока; попытка вызова из других потоков приведет к возникновению исключения
ValueError.Новое в версии 2.6.
-
signal.siginterrupt(signalnum, flag)¶ Изменяет поведение перезапуска системных вызовов: если flag равно
False, системные вызовы будут перезапущены при прерывании сигналом signalnum, в противном случае системные вызовы будут прерваны. Ничего не возвращает. Доступность: Unix (см. страницу руководства siginterrupt(3) для получения дополнительной информации).Обратите внимание, что установка обработчика сигнала с помощью
signal()сбрасывает поведение перезапуска на прерываемое, неявно вызываяsiginterrupt()со значением flag, равным true, для данного сигнала.Новое в версии 2.6.
-
signal.signal(signalnum, handler)¶ Устанавливает обработчик для сигнала signalnum равным функции handler. handler может быть вызываемым объектом Python, принимающим два аргумента (см. ниже), или одним из специальных значений
signal.SIG_IGNилиsignal.SIG_DFL. Возвращается предыдущий обработчик сигнала (см. описаниеgetsignal()выше). (См. страницу руководства Unix signal(2)).Когда потоки включены, эту функцию можно вызывать только из главного потока; попытка вызова из других потоков приведет к возникновению исключения
ValueError.handler вызывается с двумя аргументами: номером сигнала и текущим стековым кадром (
Noneили объектом кадра; описание объектов кадра см. в описании в иерархии типов или в описаниях атрибутов модуляinspect).В Windows
signal()можно вызывать только сSIGABRT,SIGFPE,SIGILL,SIGINT,SIGSEGVилиSIGTERM. В любом другом случае будет возбужденоValueError.
17.4.1. Пример¶Example
Вот минимальный пример программы. Она использует функцию alarm() для ограничения
времени, затрачиваемого на ожидание открытия файла; это полезно, если файл находится на
последовательном устройстве, которое может быть выключено, что обычно приводит к
бесконечному зависанию os.open(). Решение – установить 5-секундный будильник
перед открытием файла; если операция занимает слишком много времени, будет отправлен
сигнал будильника, и обработчик возбудит исключение.
import signal, os
def handler(signum, frame):
print 'Signal handler called with signal', signum
raise IOError("Couldn't open device!")
# Установить обработчик сигнала и 5-секундный будильник
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
# Этот вызов open() может зависнуть навсегда
fd = os.open('/dev/ttyS0', os.O_RDWR)
signal.alarm(0) # Отключить будильник