Spec-Zone.ru › Python 3.8

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.

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

END_OF_DOCUMENT_MARKER

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

Изменено в версии 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.

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

Spec-Zone.ru

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