signal
— Устанавливает обработчики асинхронных событий
Данный модуль предоставляет механизмы для использования обработчиков сигналов в Python.
Основные правила
Функция signal.signal()
позволяет определить пользовательские
обработчики, выполняемые при получении сигнала. Установлено
небольшое количество обработчиков по умолчанию: SIGPIPE
игнорируется
(поэтому об ошибках записи в конвейеры (pipes) и сокеты можно сообщать как об обычных
исключениях Python), а SIGINT
транслируется в исключение
KeyboardInterrupt
, если родительский процесс не изменил его.
Однажды установленный обработчик для определённого сигнала, остаётся
установленным до тех пор, пока он не будет явно сброшен (Python эмулирует
интерфейс в стиле BSD независимо от базовой реализации), за исключением
обработчика для SIGCHLD
, который следует базовой реализации.
Выполнение обработчиков сигналов Python
Обработчик сигналов Python не выполняется внутри низкоуровневого (C) обработчика сигналов. Вместо этого низкоуровневый обработчик сигналов устанавливает флаг, который указывает виртуальной машине выполнить соответствующий обработчик сигналов Python позже (например, при следующей инструкции байт-кода). Это приводит к последствия:
- Нет смысла перехватывать синхронные ошибки, такие как
SIGFPE
илиSIGSEGV
, вызванные недопустимой операцией в C коде. Python вернется от обработчика сигнала к C коду, который, вероятно, снова вызовет тот же сигнал, что, по-видимому, приведёт к зависанию Python. Начиная с Python 3.3, вы можете использовать модульfaulthandler
для создания отчетов об синхронных ошибках. - Длительные вычисления, реализованные исключительно на C (например, сопоставление регулярных выражений с большим текстом), могут выполняться непрерывно в течение произвольного периода времени, независимо от полученных сигналов. Будут вызваны обработчики сигналов Python, когда расчет завершится.
Сигналы и потоки
Обработчики сигналов Python всегда выполняются в основном потоке Python, даже
если сигнал был получен в другом потоке. Это означает, что сигналы нельзя
использовать в качестве средства межпотокового взаимодействия. Вместо этого вы
можете использовать примитивы синхронизации из модуля threading
.
Кроме того, только основному потоку разрешено устанавливать новый обработчик сигнала.
Содержание модуля
Изменено в версии 3.5: сигнал (SIG*), обработчик (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
Это ещё один стандартный обработчик сигналов, который просто игнорирует данный сигнал.
-
signal.
SIGABRT
Сигнал отмены от abort(3).
-
signal.
SIGALRM
Сигнал таймера от alarm(2).
Доступность: Unix.
-
signal.
SIGBREAK
Прерывание с клавиатуры (CTRL + BREAK).
Доступность: Windows.
-
signal.
SIGBUS
Ошибка шины (плохой доступ к памяти).
Доступность: Unix.
-
signal.
SIGCHLD
Дочерний процесс остановлен или завершён.
Доступность: Unix.
-
signal.
SIGCLD
Псевдоним
SIGCHLD
.
-
signal.
SIGCONT
Продолжить процесс, если он в данный момент остановлен.
Доступность: Unix.
-
signal.
SIGFPE
Исключение с плавающей запятой. Например, деление на ноль.
См.также
ZeroDivisionError
вызывается, когда второй аргумент деления или операции по модулю равен нулю.
-
signal.
SIGHUP
Обнаружено зависание на управляющем терминале или смерть управляющего процесса.
Доступность: Unix.
-
signal.
SIGILL
Незаконный оператор.
-
signal.
SIGINT
Прерывание с клавиатуры (CTRL + C).
Действие по умолчанию — вызов
KeyboardInterrupt
.
-
signal.
SIGKILL
Сигнал убийства.
Его нельзя поймать, заблокировать или проигнорировать.
Доступность: Unix.
-
signal.
SIGPIPE
Сломанная конвейер: запись в конвейер без считывателей.
Действие по умолчанию — игнорировать сигнал.
Доступность: Unix.
-
signal.
SIGSEGV
Ошибка сегментации: неверная ссылка на память.
-
signal.
SIGTERM
Сигнал завершения.
-
signal.
SIGUSR1
Пользовательский сигнал 1.
Доступность: Unix.
-
signal.
SIGUSR2
Пользовательский сигнал 2.
Доступность: Unix.
-
signal.
SIGWINCH
Сигнал изменения размера окна.
Доступность: Unix.
-
SIG*
Все номера сигналов определены символически. Например, сигнал отбоя определяется как
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) для получения дополнительной информации.
-
signal.
getsignal
(signalnum) Возвращает текущий обработчик сигнала для сигнала signalnum. Возвращаемое значение может быть вызываемым объектом Python или одним из специальных значений
signal.SIG_IGN
,signal.SIG_DFL
илиNone
. Здесьsignal.SIG_IGN
означает, что сигнал ранее игнорировался,signal.SIG_DFL
означает, что ранее использовался способ обработки сигнала по умолчанию, аNone
означает, что предыдущий обработчик сигнала не был установлен из Python.
-
signal.
strsignal
(signalnum) Возвращает системное описание сигнала signalnum, например «Прерывание», «Ошибка сегментации» и т. д. Возвращает
None
, если сигнал не распознан.Добавлено в версии 3.8.
-
signal.
valid_signals
() Возвращает множество допустимых номеров сигналов на этой платформе. Это значение может быть меньше
range(1, NSIG)
, если некоторые сигналы зарезервированы системой для внутреннего использования.Добавлено в версии 3.8.
-
signal.
pause
() Заставляет процесс спать, пока не будет получен сигнал; затем будет вызван соответствующий обработчик. Ничего не возвращает.
Доступность: Unix. См. справочную страницу signal(2) для получения дополнительной информации.
См. также
sigwait()
,sigwaitinfo()
,sigtimedwait()
иsigpending()
.
-
signal.
raise_signal
(signum) Посылает сигнал вызывающему процессу. Ничего не возвращает.
Добавлено в версии 3.8.
-
signal.
pthread_kill
(thread_id, signalnum) Отправляет сигнал signalnum в поток thread_id, другой поток в том же процессе, что и вызывающий. Целевой поток может выполнять любой код (Python или нет). Однако если целевой поток выполняет Python интерпретатор, обработчики сигналов Python будут выполняется основным потоком. Следовательно, единственной точкой отправки сигнала в конкретный поток Python будет принудительное завершение работающего системного вызова с кодом
InterruptedError
.Используйте атрибут
threading.get_ident()
илиident
объектовthreading.Thread
, чтобы получает подходящее значение для thread_id.Если signalnum равен 0, то сигнал не отправляется, но проверка ошибок все равно выполняется; это можно использовать, чтобы проверяет, работает ли ещё целевой поток.
Вызывает событие аудита
signal.pthread_kill
с аргументамиthread_id
,signalnum
.Доступность: 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
}). Используйтеvalid_signals()
для полной маски, включая все сигналы.Например,
signal.pthread_sigmask(signal.SIG_BLOCK, [])
считывает маску сигнала вызывающего потока.SIGKILL
иSIGSTOP
не могут быть заблокированы.Доступность: Unix. Смотрите справочную страницу sigprocmask(3) и pthread_sigmask(3) для получения дополнительной информации.
См. также
pause()
,sigpending()
иsigwait()
.Добавлено в версии 3.3.
-
signal.
setitimer
(which, seconds, interval=0.0) Устанавливает заданный интервальный таймер (один из
signal.ITIMER_REAL
,signal.ITIMER_VIRTUAL
илиsignal.ITIMER_PROF
), указанный which, на запуск после seconds (допустимо число с плавающей запятой, отличное отalarm()
) и после этого каждые interval секунд (если interval ненулевое). Интервальный таймер, указанный в which, можно сбросить, установив seconds в ноль.Когда срабатывает интервальный таймер, процессу отправляется сигнал. Отправленный сигнал зависит от используемого таймера;
signal.ITIMER_REAL
доставитSIGALRM
,signal.ITIMER_VIRTUAL
отправитSIGVTALRM
, аsignal.ITIMER_PROF
доставитSIGPROF
.Старые значения возвращаются в виде кортежа: (задержка, интервал).
Попытка передать недопустимый интервальный таймер приведёт к ошибке
ItimerError
.Доступность: Unix.
-
signal.
getitimer
(which) Возвращает текущее значение заданного интервального таймера, указанного в which.
Доступность: Unix.
-
signal.
set_wakeup_fd
(fd, *, warn_on_full_buffer=True) Устанавливает дескриптор файла пробуждения на fd. Когда сигнал получен, номер сигнала записывается в виде одного байта в fd. Может использоваться библиотекой для пробуждения опроса или выбора вызова, что позволяет полностью обработать сигнал.
Возвращается старое значение fd пробуждения (или -1, если пробуждение файлового дескриптора не было включено). Если fd равен -1, пробуждение файлового дескриптора отключено. Если не -1, fd должен быть неблокирующим. Библиотека должна удаляет все байты из fd перед повторным вызовом опроса или выбора.
Когда потоки включены, эту функцию можно вызывать только из основного потока; попытка вызвать его из других потоков вызовет исключение
ValueError
.Существует два распространенных способа использования этой функции. В обоих подходах вы используете fd для пробуждения при поступлении сигнала, но затем они различаются тем, как они определяют сигнал which или поступление сигналов.
При первом подходе мы считываем данные из буфера fd, а значения байтов дают вам номера сигналов. Это просто, но в редких случаях это может привести к проблемам: обычно fd имеет ограниченный объём буферного пространства, и если слишком много сигналов поступает слишком быстро, то буфер может переполниться, и некоторые сигналы могут быть потеряны. Если вы используете данный подход, вы должны установить
warn_on_full_buffer=True
, что по крайней мере приведёт к выводу предупреждения в stderr при потере сигналов.Во втором подходе мы используем wakeup fd только для пробуждения и игнорируем фактические значения байтов. В этом случае все, о чем мы заботимся, это является ли буфер fd пустым или непустым; полный буфер вообще не указывает на проблему. Если вы используете данный подход, вы должны установить
warn_on_full_buffer=False
, чтобы ваши пользователи не были сбиты с толку ложными предупреждающими сообщениями.Изменено в версии 3.5: В Windows данная функция теперь также поддерживает дескрипторы сокетов.
Изменено в версии 3.7: Добавлен параметр
warn_on_full_buffer
.
-
signal.
siginterrupt
(signalnum, flag) Изменяет поведение перезапуска системного вызова: если flag равен
False
, системные вызовы будут перезапущены при прерывании сигналом signalnum, в противном случае системные вызовы будут прерваны. Ничего не возвращает.Доступность: Unix. См. справочную страницу siginterrupt(3) для дополнительной информации.
Обратите внимание, что установка обработчика сигнала с
signal()
сбросит режим перезапуска до прерываемого путём неявного вызоваsiginterrupt()
с истинным значением flag для данного сигнала.
-
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. См. справочную страницу sigtimedwait(2) для получения дополнительной информации.
См. также
pause()
,sigwait()
иsigwaitinfo()
.Добавлено в версии 3.3.
Изменено в версии 3.5: Функция теперь повторяется с перевычисленным timeout, если она прерывается сигналом, отличным от sigset, и обработчик сигнала не вызывает исключение (обоснование см. в PEP 475).
Пример
Вот минимальный пример программы. Она использует функцию alarm()
, чтобы
ограничить время ожидания открытия файла; это полезно, если файл предназначен
для последовательного устройства, которое может быть не включено, что обычно
приводит к зависанию os.open()
на неопределенный срок. Решение состоит в
том, чтобы установить 5-секундный будильник перед открытием файла; если
операция занимает слишком много времени, будет отправлен сигнал тревоги, и
обработчик вызовет исключение.
import signal, os
def handler(signum, frame):
print('Обработчик сигнала вызывается с помощью signal', signum)
raise OSError("Не удалось открыть устройство!")
# Устанавливает обработчик сигнала и 5-секундный сигнал тревоги
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
# Tего open() может зависать бесконечно
fd = os.open('/dev/ttyS0', os.O_RDWR)
signal.alarm(0) # Отключает сигнализацию
Примечание по SIGPIPE
Передача вывода вашей программы на такие инструменты, как head(1),
приведёт к отправке сигнала SIGPIPE
в ваш процесс, когда приемник его
стандартного вывода закрывается раньше времени. Это приводит к исключению типа
BrokenPipeError: [Errno 32] Broken pipe
. Чтобы справиться с этим
случаем, оборачивает точку входа, чтобы перехватить это исключение, следующим
образом:
import os
import sys
def main():
try:
# имитирует большой вывод (ваш код заменяет этот цикл)
for x in range(10000):
print("y")
# сбросывает вывод здесь, чтобы принудительно запустить SIGPIPE
# находясь внутри этого блока try.
sys.stdout.flush()
except BrokenPipeError:
# Python сбрасывает стандартные потоки при выходе; перенаправляет оставшийся вывод
# к dev null, чтобы избежать еще одной ошибки прерывания конвейера при завершении работы
devnull = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, sys.stdout.fileno())
sys.exit(1) # Python завершает работу с кодом ошибки 1 в EPIPE
if __name__ == '__main__':
main()
Не устанавливайте расположение SIGPIPE
в SIG_DFL
, чтобы
избежать BrokenPipeError
. Это приведёт к неожиданному выходу вашей
программы также всякий раз, когда любое соединение сокета прерывается, пока
ваша программа все ещё записывает в него.