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 -
Процесс-потомок приостановлен или завершен.
Доступность: 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 (принимает float, отличается от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. Это может использоваться библиотекой для пробуждения вызовов 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–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/signal.html