signal — Установка обработчиков для асинхронных событий
Этот модуль предоставляет механизмы для использования обработчиков сигналов в Python.
Общие правила
Функция signal.signal() позволяет определить пользовательские обработчики, которые будут выполняться при получении сигнала. Установлено небольшое количество обработчиков по умолчанию: SIGPIPE игнорируется (чтобы ошибки записи в трубы и сокеты можно было сообщать как обычные исключения 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 -
Дочерний процесс остановлен или завершен.
Доступность: Windows.
-
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.pause() -
Заставляет процесс спать до получения сигнала; затем будет вызван соответствующий обработчик. Ничего не возвращает.
Доступность: 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, [])считывает маску сигналов вызывающей потоковой нити.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 (принимает float, отличается отalarm()) и после этого каждые interval секунд (если 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, *, warn_on_full_buffer=True) -
Устанавливает дескриптор файла для пробуждения в fd. Когда принимается сигнал, номер сигнала записывается как один байт в fd. Это можно использовать библиотекой для пробуждения вызова poll или select, позволяя полностью обработать сигнал.
Возвращает старый дескриптор файла пробуждения (или -1, если пробуждение по дескриптору файла не было включено). Если fd равен -1, пробуждение по дескриптору файла отключается. Если не -1, fd должен быть асинхронным. Библиотеке необходимо удалить все байты из fd перед повторным вызовом poll или select.
При включении потоков этот метод можно вызывать только из основной потоковой нити; попытка вызова из других потоков приведет к исключению
ValueError.Существует два распространенных способа использования этой функции. В обоих подходах вы используете fd для пробуждения при поступлении сигнала, но они различаются по тому, как определяются какой сигнал или сигналы поступили.
В первом подходе мы считываем данные из буфера fd, и значения байтов дают вам номера сигналов. Это просто, но в редких случаях это может вызвать проблему: обычно fd имеет ограниченный объем буфера, и если слишком много сигналов поступает слишком быстро, буфер может заполниться, и некоторые сигналы могут быть потеряны. Если вы используете этот подход, установите
warn_on_full_buffer=True, что по крайней мере приведет к выводу предупреждения в stderr, когда сигналы теряются.Во втором подходе мы используем 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 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. Смотрите страницу руководства 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 handler called with signal', signum)
raise OSError("Couldn't open device!")
# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)
signal.alarm(0) # Disable the alarm
Примечание по SIGPIPE
Перенаправление вывода вашей программы в инструменты, такие как head(1), вызовет отправку сигнала SIGPIPE вашему процессу, когда получатель стандартного вывода закрывается раньше. Это приводит к исключению типа BrokenPipeError: [Errno 32] Broken pipe. Чтобы обработать этот случай, оберните точку входа, чтобы перехватить это исключение следующим образом:
import os
import sys
def main():
try:
# simulate large output (your code replaces this loop)
for x in range(10000):
print("y")
# flush output here to force SIGPIPE to be triggered
# while inside this try block.
sys.stdout.flush()
except BrokenPipeError:
# Python flushes standard streams on exit; redirect remaining output
# to devnull to avoid another BrokenPipeError at shutdown
devnull = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, sys.stdout.fileno())
sys.exit(1) # Python exits with error code 1 on EPIPE
if __name__ == '__main__':
main()
Не устанавливайте обработку сигнала SIGPIPE в значение SIG_DFL, чтобы избежать BrokenPipeError. В противном случае ваша программа неожиданно завершится также всякий раз, когда соединение сокета прерывается, пока ваша программа всё ещё записывает в него.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.7/library/signal.html