signal — Установить обработчики для асинхронных событий


Модуль обеспечивает механизмы для использования обработчиков сигналов в Python.

Общие правила

Функция signal.signal() позволяет определять пользовательские обработчики, которые будут выполнены, когда сигнал получен. Установлено небольшое количество обработчиков по умолчанию: SIGPIPE игнорируется (поэтому ошибки записи в пайпы и сокеты можно сообщать как обычные Python исключения) и SIGINT преобразуется в исключение KeyboardInterrupt, если родительский процесс не изменил его.

Обработчик для определенного сигнала после его установки остается установленным до явный сброс (Python эмулирует интерфейс в стиле BSD независимо от базовая реализация), за исключением обработчика для SIGCHLD, который следует за базовой реализацией.

Выполнение сигнала Python обработчики

Обработчик сигнала Python не становится выполненным на низкоуровневом (C) обработчике сигнала. Вместо этого низкоуровневое сигнал обработчик устанавливает флаг, который предписывает виртуальной машине выполнить соответствующий Python сигнал обработчик в более поздней точке (например, в следующей команде байт-кода). Это имеет последствия:

  • Имеет мало смысла фиксировать синхронные ошибки как SIGFPE или SIGSEGV, которые вызваны недействительной операцией в C код. Python будет возвращает от сигнала обработчик к C код, который, вероятно, снова поднимет тот же сигнал, что, по-видимому, приведет к зависанию Python. Начиная с Python 3.3 можно использовать модуль mod:faulthandler для создания отчетов о синхронных ошибках.
  • Продолжительное вычисление, реализованное исключительно в C (например, сопоставление регулярных выражений на большом теле текста), может работать непрерывно в течение произвольного периода времени, независимо от любых принятых сигналов. Сигнал обработчики Python назовут, когда вычисление закончится.

Сигналы и потоки

Python обработчики сигнала всегда выполняется в основном Python потоке, даже если сигнал был принят в другом потоке. Это означает, что сигналы не могут быть используемый как средство inter-поток связи. Вместо этого можно использовать примитивы синхронизации из модуля threading.

Кроме того, только главному поток позволяют установить новый сигнал обработчик.

Содержимое модуля

Изменено в версии 3.5: Перечисленные ниже константы сигнала (SIG*), обработчик (SIG_DFL, SIG_IGN) и сигмаски (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).

Availability: Unix.

signal.SIGBREAK

Прерывание с клавиатуры (CTRL + BREAK).

Availability: Windows.

signal.SIGBUS

Ошибка шины (неправильный доступ к памяти).

Availability: Unix.

signal.SIGCHLD

Дочерний процесс остановлен или завершен.

Availability: Unix.

signal.SIGCLD

Псевдоним SIGCHLD.

signal.SIGCONT

Продолжить процесс, если он в данный момент остановлен

Availability: Unix.

signal.SIGFPE

Исключение с плавающей запятой. Например, деление на ноль.

См.также

ZeroDivisionError возводится, когда второй аргумент операции деления или операции по модулю равен нулю.

signal.SIGHUP

Обнаружение зависания на управляющем терминале или прекращение процесса управления.

Availability: Unix.

signal.SIGILL

Недопустимая инструкция.

signal.SIGINT

Прерывание с клавиатуры (CTRL + C).

Действие по умолчанию - поднять KeyboardInterrupt.

signal.SIGKILL

Сигнал об убийстве.

Его нельзя поймать, заблокировать или игнорировать.

Availability: Unix.

signal.SIGPIPE

Сломанные пайп: пишите пайп без читателей.

Действие по умолчанию - игнорировать сигнал.

Availability: Unix.

signal.SIGSEGV

Ошибка сегментации: недопустимая ссылка на память.

signal.SIGTERM

Сигнал окончания.

signal.SIGUSR1

Пользовательский сигнал 1.

Availability: Unix.

signal.SIGUSR2

Пользовательский сигнал 2.

Availability: Unix.

signal.SIGWINCH

Сигнал изменения размера окна.

Availability: Unix.

SIG*

Все номера сигналов определяются символически. Например, сигнал зависания определяется как signal.SIGHUP; имена переменной идентичны именам используемый в программах C, как найдено в <signal.h>. Справочная страница Unix для „signal()“ перечисляет существующие сигналы (на некоторых системах это signal(2), на других список в signal(7)). Следует отметить, что не все системы определяют один и тот же набор имен сигналов; только те имена, которые определены системой, определяются этим модулем.

signal.CTRL_C_EVENT

Сигнал, соответствующий событию нажатия клавиши Ctrl+C. Этот сигнал может быть используемый только с os.kill().

Availability: Windows.

Добавлено в версии 3.2.

signal.CTRL_BREAK_EVENT

Сигнал, соответствующий событию нажатия клавиши Ctrl+Break. Этот сигнал может быть используемый только с os.kill().

Availability: 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.

Добавлено в версии 3.3: Этот ошибочный используемый, чтобы быть подтипом IOError, который является теперь алиас OSError.

Модуль signal определяет следующие функции:

signal.alarm(time)

Если значение time не равно нулю, эта функция запрашивает передачу сигнала SIGALRM в процесс через time секунд. Любой ранее запланированный аварийный сигнал отменяется (только один аварийный сигнал может быть запланирован в любое время). В этом случае возвращенный значение - это число секунд до того, как должен был быть доставлен любой ранее установленный аварийный сигнал. Если time равен нулю, никакой аварийный сигнал не запланирован, и любой запланированный аварийный сигнал отменяется. Если значение возвращает значение равно нулю, в настоящее время аварийный сигнал не запланирован.

Availability: 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()

Привести процесс в спящий режим до тех пор, пока сигнал не будет принят; затем будет вызван соответствующий обработчик. Возвращает ничего.

Availability: 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, то сигнал не посылается, но проверка ошибок по- прежнему выполняется; это может быть используемый, чтобы проверить, бежит ли целевой поток все еще.

Raises an auditing event signal.pthread_kill with arguments thread_id, signalnum.

Availability: 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 не могут быть заблокированы.

Availability: Unix. See the man page sigprocmask(3) and 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.

Availability: Unix.

signal.getitimer(which)

Возвращает текущее значение данного таймера интервала определеного which.

Availability: 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 при потере сигналов.

Во втором подходе мы используем пробуждение fd только для пробуждения и игнорируем фактический байт значения. В этом случае все, что нас волнует, это пустой или непустой буфер fd; полный буфер вообще не указывает на проблему. Если вы используете этот подход, то вы должны установить warn_on_full_buffer=False, чтобы ваши пользователи не были запутаны ложными предупреждающими сообщениями.

Изменено в версии 3.5: На Windows функция теперь также поддерживает обработчики сокета.

Изменено в версии 3.7: Добавлен параметр warn_on_full_buffer.

signal.siginterrupt(signalnum, flag)

Изменение поведения перезапуска системных вызовов: если flag является False, системные вызовы будут перезапущены при прерывании по сигналу signalnum, в противном случае системные вызовы будут прерваны. Возвращает ничего.

Availability: 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()

Исследовать набор сигналов, которые находятся на рассмотрении для доставки к запросу поток (т.е. сигналы, которые были подняты, в то время как заблокировано). Возвращает набор ожидающих сигналов.

Availability: Unix. Для получения дополнительной информации см. справочную страницу sigpending(2).

См. также pause(), pthread_sigmask() и sigwait().

Добавлено в версии 3.3.

signal.sigwait(sigset)

Приостановите выполнение запроса поток, пока доставка одного из сигналов, определенных в сигнале, не установит sigset. Функция принимает сигнал (удаляет его из списка ожидающих сигналов) и возвращает номер сигнала.

Availability: Unix. Смотрите man страницу sigwaitinfo (2) для дальнейшей информации информация.

См. также pause(), pthread_sigmask(), sigpending(), sigwaitinfo() и sigtimedwait().

Добавлено в версии 3.3.

signal.sigwaitinfo(sigset)

Приостановить выполнение запроса поток, пока доставка одного из сигналов, определенных в сигнале, не установит sigset. Функция принимает сигнал и удаляет его из списка ожидающих сигналов. Если один из сигналов в sigset уже будет находиться на рассмотрении для запроса поток, то функция немедленно будет возвращает с информацией о том сигнале. Сигнал обработчик не вызывается для доставленного сигнала. Функция вызывает InterruptedError, если она прерывается сигналом, который не находится в sigset.

возвращает значение - объект, представляющий данные, содержавшиеся в the:c:type:siginfo_t структуре, а именно: si_signo, si_code, si_errno, si_pid, si_uid, si_status, si_band.

Availability: Unix. Для получения дополнительной информации см. справочную страницу sigwaitinfo(2).

См. также pause(), sigwait() и sigtimedwait().

Добавлено в версии 3.3.

Изменено в версии 3.5: Теперь функция повторяется, если прерывается сигналом, не находящимся в sigset, и сигнал обработчик не вызывает исключения (обоснование см. в разделе PEP 475).

signal.sigtimedwait(sigset, timeout)

Как и sigwaitinfo(), но принимает дополнительный аргумент timeout, указывающий тайм-аут. Если параметр timeout указан как 0, выполняется опрос. Возвращает None в случае тайм-аута.

Availability: Unix. Смотрите страницу man 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!")

# Установить обработчик сигнала и 5-секундный аварийный сигнал
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# open() может зависать бесконечно
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Отключить alarm

Примечание к 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 промывает стандартные потоки на выходе; перенаправить оставшиеся выходные
        # данные на devnull, чтобы избежать другой BrokenPipeError при завершении работы
        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. Это приведет к неожиданному завершению работы программы при прерывании любого сокет соединения во время записи в программу.