Содержание страницы
18.8. signal – Установка обработчиков для асинхронных событий¶signal – Set handlers for asynchronous events
Этот модуль предоставляет механизмы для использования обработчиков сигналов в Python.
18.8.1. Общие правила¶General rules
Функция signal.signal() позволяет определять пользовательские обработчики,
которые выполняются при получении сигнала. Установлено небольшое количество обработчиков по умолчанию: SIGPIPE игнорируется (поэтому ошибки записи в каналы и сокеты могут сообщаться как обычные исключения Python), а SIGINT преобразуется в исключение KeyboardInterrupt.
Обработчик конкретного сигнала после установки остается активным до
явной переустановки (Python эмулирует интерфейс в стиле BSD независимо от
реализации), за исключением обработчика для
SIGCHLD, который следует базовой реализации.
18.8.1.1. Выполнение обработчиков сигналов Python¶Execution of Python signal handlers
Обработчик сигналов Python не выполняется внутри низкоуровневого (C) обработчика сигналов. Вместо этого низкоуровневый обработчик устанавливает флаг, который сообщает виртуальной машине выполнить соответствующий обработчик Python позже (например, на следующей инструкции байткода). Это имеет последствия:
Ловить синхронные ошибки вроде
SIGFPEилиSIGSEGV, вызванные недопустимой операцией в коде C, не имеет смысла. Python вернется от обработчика сигнала к коду C, который, скорее всего, снова возбудит тот же сигнал, что приведет к зависанию Python. Начиная с Python 3.3 можно использовать модульfaulthandlerдля сообщения о синхронных ошибках.Длительное вычисление, реализованное чисто на C (например, сравнение с регулярным выражением по большому объему текста), может выполняться без прерывания сколь угодно долго, независимо от полученных сигналов. Обработчики сигналов Python будут вызваны по завершении вычисления.
18.8.1.2. Сигналы и потоки¶Signals and threads
Обработчики сигналов Python всегда выполняются в главном потоке Python, даже если сигнал был получен в другом потоке. Это означает, что сигналы нельзя использовать для межпоточной коммуникации. Вместо этого можно использовать примитивы синхронизации из модуля threading.
Кроме того, только главный поток может устанавливать новый обработчик сигнала.
18.8.2. Содержимое модуля¶Module contents
Изменено в версии 3.5: signal (SIG*), handler (SIG_DFL, SIG_IGN) и sigmask
(SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK)
и перечисленные ниже константы были преобразованы в
enums.
Функции getsignal(), pthread_sigmask(), sigpending() и
sigwait() возвращают человекочитаемые
enums.
Переменные, определенные в модуле 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.
Новое в версии 3.2.
-
signal.CTRL_BREAK_EVENT¶ Сигнал, соответствующий нажатию клавиши Ctrl+Break. Этот сигнал можно использовать только с
os.kill().Доступность: Windows.
Новое в версии 3.2.
-
signal.NSIG¶ На единицу больше номера самого высокого сигнала.
-
signal.ITIMER_REAL¶ Уменьшает интервальный таймер в реальном времени и отправляет
SIGALRMпо истечении.
-
signal.ITIMER_VIRTUAL¶ Уменьшает интервальный таймер только во время выполнения процесса и отправляет SIGVTALRM по истечении.
-
signal.ITIMER_PROF¶ Уменьшает интервальный таймер как при выполнении процесса, так и при выполнении системой от имени процесса. В паре с ITIMER_VIRTUAL этот таймер обычно используется для профилирования времени, затраченного приложением в пользовательском и ядерном пространстве. SIGPROF доставляется по истечении времени.
-
signal.SIG_BLOCK¶ Возможное значение параметра how функции
pthread_sigmask(), указывающее, что сигналы должны быть заблокированы.Новое в версии 3.3.
-
signal.SIG_UNBLOCK¶ Возможное значение параметра how функции
pthread_sigmask(), указывающее, что сигналы должны быть разблокированы.Новое в версии 3.3.
-
signal.SIG_SETMASK¶ Возможное значение параметра how функции
pthread_sigmask(), указывающее, что маска сигналов должна быть заменена.Новое в версии 3.3.
Модуль signal определяет одно исключение:
-
exception
signal.ItimerError¶ Возбуждается для указания на ошибку в реализации
setitimer()илиgetitimer(). Этого исключения следует ожидать, если некорректный интервальный таймер или отрицательное время передаются вsetitimer(). Это исключение является подтипомOSError.
Модуль 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).)
См. также
sigwait(),sigwaitinfo(),sigtimedwait()иsigpending().
-
signal.pthread_kill(thread_id, signalnum)¶ Посылает сигнал signalnum потоку thread_id, другому потоку в том же процессе, что и вызывающий. Целевой поток может выполнять любой код (Python или нет). Однако, если целевой поток выполняет интерпретатор Python, обработчики сигналов Python будут выполнены главным потоком. Следовательно, единственный смысл отправки сигнала конкретному потоку Python – это принудительное завершение работающего системного вызова с ошибкой
InterruptedError.Используйте
threading.get_ident()или атрибутidentобъектовthreading.Thread, чтобы получить подходящее значение для thread_id.Если signalnum равен 0, сигнал не отправляется, но проверка ошибок по-прежнему выполняется; это можно использовать для проверки, работает ли целевой поток.
Доступность: Unix (см. страницу руководства pthread_kill(3) для получения дополнительной информации).
См. также
os.kill().Новое в версии 3.3.
-
signal.pthread_sigmask(how, mask)¶ Получает и/или изменяет маску сигналов вызывающего потока. Маска сигналов – это набор сигналов, доставка которых в настоящий момент заблокирована для вызывающей стороны. Возвращает старую маску сигналов в виде набора сигналов.
Поведение вызова зависит от значения how следующим образом.
SIG_BLOCK: Набор заблокированных сигналов – это объединение текущего набора и аргумента mask.SIG_UNBLOCK: Сигналы из mask удаляются из текущего набора заблокированных сигналов. Допускается попытка разблокировать сигнал, который не был заблокирован.SIG_SETMASK: Набор заблокированных сигналов устанавливается равным аргументу mask.
mask – это множество номеров сигналов (например, {
signal.SIGINT,signal.SIGTERM}). Для полной маски, включающей все сигналы, используйтеrange(1, signal.NSIG).Например,
signal.pthread_sigmask(signal.SIG_BLOCK, [])считывает маску сигналов вызывающего потока.Доступность: Unix. См. страницы руководства sigprocmask(3) и pthread_sigmask(3) для получения дополнительной информации.
См. также
pause(),sigpending()иsigwait().Новое в версии 3.3.
-
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.
-
signal.getitimer(which)¶ Возвращает текущее значение указанного интервального таймера, заданного через which. Доступность: Unix.
-
signal.set_wakeup_fd(fd)¶ Устанавливает дескриптор файла пробуждения в fd. Когда сигнал получен, номер сигнала записывается в fd как один байт. Это может быть использовано библиотекой для пробуждения вызова poll или select, позволяя полностью обработать сигнал.
Возвращается старый fd пробуждения (или -1, если пробуждение через файловый дескриптор не было включено). Если fd равен -1, пробуждение через файловый дескриптор отключается. Если не -1, то fd должен быть неблокирующим. Задача библиотеки – удалить все байты из fd перед повторным вызовом poll или select.
Используйте, например,
struct.unpack('%uB' % len(data), data)для декодирования списка номеров сигналов.Когда потоки включены, эту функцию можно вызывать только из главного потока; попытка вызова из других потоков приведет к возникновению исключения
ValueError.Изменено в версии 3.5: В Windows функция теперь также поддерживает дескрипторы сокетов.
-
signal.siginterrupt(signalnum, flag)¶ Изменяет поведение перезапуска системных вызовов: если flag равно
False, системные вызовы будут перезапущены при прерывании сигналом signalnum, в противном случае системные вызовы будут прерваны. Ничего не возвращает. Доступность: Unix (см. страницу руководства siginterrupt(3) для получения дополнительной информации).Обратите внимание, что установка обработчика сигнала с помощью
signal()сбрасывает поведение перезапуска на прерываемое, неявно вызываяsiginterrupt()со значением flag, равным true, для данного сигнала.
-
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илиSIGBREAK. В любом другом случае будет возбужденоValueError. Обратите внимание, что не все системы определяют одинаковый набор имён сигналов;AttributeErrorбудет возбуждено, если имя сигнала не определено как константа уровня модуляSIG*.
-
signal.sigpending()¶ Проверяет набор сигналов, ожидающих доставки вызывающему потоку (т.е. сигналы, которые были подняты, пока были заблокированы). Возвращает набор ожидающих сигналов.
Доступность: Unix (см. страницу руководства sigpending(2) для получения дополнительной информации).
См. также
pause(),pthread_sigmask()иsigwait().Новое в версии 3.3.
-
signal.sigwait(sigset)¶ Приостанавливает выполнение вызывающего потока до доставки одного из сигналов, указанных в наборе сигналов sigset. Функция принимает сигнал (удаляет его из списка ожидающих сигналов) и возвращает номер сигнала.
Доступность: Unix (см. страницу руководства sigwait(3) для получения дополнительной информации).
См. также
pause(),pthread_sigmask(),sigpending(),sigwaitinfo()иsigtimedwait().Новое в версии 3.3.
-
signal.sigwaitinfo(sigset)¶ Приостанавливает выполнение вызывающего потока до доставки одного из сигналов, указанных в наборе сигналов sigset. Функция принимает сигнал и удаляет его из списка ожидающих сигналов. Если один из сигналов в sigset уже ожидает вызывающий поток, функция немедленно вернётся с информацией об этом сигнале. Обработчик сигнала не вызывается для доставленного сигнала. Функция возбуждает
InterruptedError, если она была прервана сигналом, которого нет в sigset.Возвращаемое значение – объект, представляющий данные, содержащиеся в структуре
siginfo_t, а именно:si_signo,si_code,si_errno,si_pid,si_uid,si_status,si_band.Доступность: Unix (см. страницу руководства sigwaitinfo(2) для получения дополнительной информации).
См. также
pause(),sigwait()иsigtimedwait().Новое в версии 3.3.
Изменено в версии 3.5: Теперь функция повторяется, если прервана сигналом, не входящим в sigset, и обработчик сигнала не возбуждает исключение (см. PEP 475 для обоснования).
-
signal.sigtimedwait(sigset, timeout)¶ Как
sigwaitinfo(), но принимает дополнительный аргумент timeout, указывающий тайм-аут. Если timeout указан как0, выполняется опрос. ВозвращаетNoneпри наступлении тайм-аута.Доступно: Unix (см. man-страницу sigtimedwait(2) для получения дополнительной информации).
См. также
pause(),sigwait()иsigwaitinfo().Новое в версии 3.3.
Изменено в версии 3.5: Теперь функция повторяется с пересчитанным timeout, если прервана сигналом, не входящим в sigset, и обработчик сигнала не возбуждает исключение (см. PEP 475 для обоснования).
18.8.3. Пример¶Example
Вот минимальный пример программы. Она использует функцию alarm() для ограничения
времени, затрачиваемого на ожидание открытия файла; это полезно, если файл находится на
последовательном устройстве, которое может быть выключено, что обычно приводит к
бесконечному зависанию os.open(). Решение – установить 5-секундный будильник
перед открытием файла; если операция занимает слишком много времени, будет отправлен
сигнал будильника, и обработчик возбудит исключение.
import signal, os
def handler(signum, frame):
print('Signal handler called with signal', signum)
raise OSError("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) # Отключить будильник