Spec-Zone.ru › Python 3.7

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)). Обратите внимание, что не все системы определяют один и тот же набор имён сигналов; только те имена сигналов, которые определены системой, определены в данном модуле.

END_OF_DOCUMENT_MARKER
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.

Введено в версии 3.3: Эта ошибка ранее была подклассом IOError, которая сейчас является псевдонимом 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API