signal.md
1> **Источник:** https://python-all.ru/3.15/library/signal.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `signal` – Установка обработчиков асинхронных событий89**Исходный код:** [Lib/signal.py](https://python-all.ru/src/3.15/Lib/signal.py)1011---1213Этот модуль предоставляет механизмы для использования обработчиков сигналов в Python.1415## Общие правила1617Функция [`signal.signal()`](https://python-all.ru/3.15/library/signal.html#signal.signal) позволяет определять пользовательские обработчики, выполняемые при получении сигнала. Небольшое количество обработчиков по умолчанию установлено: сигнал [`SIGPIPE`](https://python-all.ru/3.15/library/signal.html#signal.SIGPIPE) игнорируется (поэтому ошибки записи в каналы и сокеты могут сообщаться как обычные исключения Python), а сигнал [`SIGINT`](https://python-all.ru/3.15/library/signal.html#signal.SIGINT) преобразуется в исключение [`KeyboardInterrupt`](https://python-all.ru/3.15/library/exceptions.html#KeyboardInterrupt), если родительский процесс не изменил его.1819Обработчик конкретного сигнала после установки остается активным до явной переустановки (Python эмулирует интерфейс в стиле BSD независимо от реализации), за исключением обработчика для [`SIGCHLD`](https://python-all.ru/3.15/library/signal.html#signal.SIGCHLD), который следует базовой реализации.2021На платформах WebAssembly сигналы эмулируются и поэтому ведут себя иначе. Некоторые функции и сигналы на этих платформах недоступны.2223### Выполнение обработчиков сигналов Python2425Обработчик сигнала Python не выполняется внутри низкоуровневого (C) обработчика сигналов. Вместо этого низкоуровневый обработчик устанавливает флаг, который сообщает [виртуальной машине](https://python-all.ru/3.15/glossary.html#term-virtual-machine) выполнить соответствующий обработчик сигнала Python в более поздний момент (например, на следующей инструкции [байткода](https://python-all.ru/3.15/glossary.html#term-bytecode)). Это имеет последствия:2627- Ловить синхронные ошибки вроде [`SIGFPE`](https://python-all.ru/3.15/library/signal.html#signal.SIGFPE) или [`SIGSEGV`](https://python-all.ru/3.15/library/signal.html#signal.SIGSEGV), вызванные недопустимой операцией в коде C, не имеет смысла. Python вернется от обработчика сигнала к коду C, который, скорее всего, снова возбудит тот же сигнал, что приведет к зависанию Python. Начиная с Python 3.3 можно использовать модуль [`faulthandler`](https://python-all.ru/3.15/library/faulthandler.html#module-faulthandler) для сообщения о синхронных ошибках.28- Длительное вычисление, реализованное чисто на C (например, сравнение с регулярным выражением по большому объему текста), может выполняться без прерывания сколь угодно долго, независимо от полученных сигналов. Обработчики сигналов Python будут вызваны по завершении вычисления.29- Если обработчик возбуждает исключение, оно будет возбуждено «из ниоткуда» в основном потоке. См. [примечание ниже](https://python-all.ru/3.15/library/signal.html#handlers-and-exceptions) для обсуждения.3031### Сигналы и потоки3233Обработчики сигналов Python всегда выполняются в главном потоке Python главного интерпретатора, даже если сигнал был получен в другом потоке. Это означает, что сигналы нельзя использовать как средство межпотокового взаимодействия. Вместо этого можно использовать примитивы синхронизации из модуля [`threading`](https://python-all.ru/3.15/library/threading.html#module-threading).3435Кроме того, только главный поток главного интерпретатора может устанавливать новый обработчик сигнала.3637> **Предупреждение**38>39> Примитивы синхронизации, такие как [`threading.Lock`](https://python-all.ru/3.15/library/threading.html#threading.Lock), не следует использовать внутри обработчиков сигналов. Это может привести к неожиданным взаимоблокировкам.4041## Содержимое модуля4243Изменено в версии 3.5: константы, связанные с сигналами (SIG\*), обработчиками ([`SIG_DFL`](https://python-all.ru/3.15/library/signal.html#signal.SIG_DFL), [`SIG_IGN`](https://python-all.ru/3.15/library/signal.html#signal.SIG_IGN)) и сигнальными масками ([`SIG_BLOCK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_BLOCK), [`SIG_UNBLOCK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_UNBLOCK), [`SIG_SETMASK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_SETMASK)) перечисленные ниже, были преобразованы в [`enums`](https://python-all.ru/3.15/library/enum.html#enum.IntEnum) (соответственно [`Signals`](https://python-all.ru/3.15/library/signal.html#signal.Signals), [`Handlers`](https://python-all.ru/3.15/library/signal.html#signal.Handlers) и [`Sigmasks`](https://python-all.ru/3.15/library/signal.html#signal.Sigmasks)). Функции [`getsignal()`](https://python-all.ru/3.15/library/signal.html#signal.getsignal), [`pthread_sigmask()`](https://python-all.ru/3.15/library/signal.html#signal.pthread_sigmask), [`sigpending()`](https://python-all.ru/3.15/library/signal.html#signal.sigpending) и [`sigwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigwait) возвращают человекочитаемые `enums` в виде объектов `Signals`.4445Модуль signal определяет три перечисления:4647#### `class signal.Signals`4849[`enum.IntEnum`](https://python-all.ru/3.15/library/enum.html#enum.IntEnum) набор констант SIG\* и констант CTRL\_\*.5051Добавлено в версии 3.5.5253#### `class signal.Handlers`5455[`enum.IntEnum`](https://python-all.ru/3.15/library/enum.html#enum.IntEnum) набор констант [`SIG_DFL`](https://python-all.ru/3.15/library/signal.html#signal.SIG_DFL) и [`SIG_IGN`](https://python-all.ru/3.15/library/signal.html#signal.SIG_IGN).5657Добавлено в версии 3.5.5859#### `class signal.Sigmasks`6061[`enum.IntEnum`](https://python-all.ru/3.15/library/enum.html#enum.IntEnum) набор констант [`SIG_BLOCK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_BLOCK), [`SIG_UNBLOCK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_UNBLOCK) и [`SIG_SETMASK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_SETMASK).6263[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.6465Смотрите man-страницу *[sigprocmask(2)](https://python-all.ru/3.15/library/signal.html)* и *[pthread\_sigmask(3)](https://python-all.ru/3.15/library/signal.html)* для получения дополнительной информации.6667Добавлено в версии 3.5.6869Переменные, определенные в модуле `signal`:7071#### `signal.SIG_DFL`7273Это один из двух стандартных вариантов обработки сигналов; он просто выполняет функцию по умолчанию для сигнала. Например, на большинстве систем действие по умолчанию для [`SIGQUIT`](https://python-all.ru/3.15/library/signal.html#signal.SIGQUIT) – сбросить дамп ядра и завершиться, тогда как действие по умолчанию для [`SIGCHLD`](https://python-all.ru/3.15/library/signal.html#signal.SIGCHLD) – просто игнорировать его.7475#### `signal.SIG_IGN`7677Это еще один стандартный обработчик сигнала, который просто игнорирует данный сигнал.7879#### `signal.SIGABRT`8081Сигнал прерывания от *[abort(3)](https://python-all.ru/3.15/library/signal.html)*.8283#### `signal.SIGALRM`8485Сигнал таймера от *[alarm(2)](https://python-all.ru/3.15/library/signal.html)*.8687[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.8889#### `signal.SIGBREAK`9091Прерывание с клавиатуры (CTRL + BREAK).9293[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Windows.9495#### `signal.SIGBUS`9697Ошибка шины (неверный доступ к памяти).9899[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.100101#### `signal.SIGCHLD`102103Дочерний процесс остановлен или завершён.104105[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.106107#### `signal.SIGCLD`108109Псевдоним для [`SIGCHLD`](https://python-all.ru/3.15/library/signal.html#signal.SIGCHLD).110111[Доступность](https://python-all.ru/3.15/library/intro.html#availability): не macOS.112113#### `signal.SIGCONT`114115Продолжить процесс, если он в данный момент остановлен116117[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.118119#### `signal.SIGFPE`120121Исключение с плавающей запятой. Например, деление на ноль.122123> **См. также**124>125> [`ZeroDivisionError`](https://python-all.ru/3.15/library/exceptions.html#ZeroDivisionError) возникает, когда второй аргумент операции деления или взятия остатка равен нулю.126127#### `signal.SIGHUP`128129Обнаружен обрыв связи на управляющем терминале или завершение управляющего процесса.130131[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.132133#### `signal.SIGILL`134135Недопустимая инструкция.136137#### `signal.SIGINT`138139Прерывание с клавиатуры (CTRL + C).140141Действие по умолчанию – возбудить [`KeyboardInterrupt`](https://python-all.ru/3.15/library/exceptions.html#KeyboardInterrupt).142143#### `signal.SIGKILL`144145Сигнал уничтожения.146147Его нельзя перехватить, заблокировать или проигнорировать.148149[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.150151#### `signal.SIGPIPE`152153Разрыв канала: запись в канал без читателей.154155Действие по умолчанию – игнорировать сигнал.156157[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.158159#### `signal.SIGPROF`160161Таймер профилирования истёк.162163[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.164165#### `signal.SIGQUIT`166167Сигнал выхода терминала.168169[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.170171#### `signal.SIGSEGV`172173Ошибка сегментации: неверная ссылка на память.174175#### `signal.SIGSTOP`176177Остановка выполнения (не может быть перехвачен или проигнорирован).178179[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.180181#### `signal.SIGSTKFLT`182183Сбой стека на сопроцессоре. Ядро Linux не генерирует этот сигнал: он может быть вызван только из пользовательского пространства.184185[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Linux.186187На архитектурах, где этот сигнал доступен. См. страницу руководства *[signal(7)](https://python-all.ru/3.15/library/signal.html)* для получения дополнительных сведений.188189Добавлено в версии 3.12.190191#### `signal.SIGTERM`192193Сигнал завершения.194195#### `signal.SIGUSR1`196197Пользовательский сигнал 1.198199[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.200201#### `signal.SIGUSR2`202203Пользовательский сигнал 2.204205[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.206207#### `signal.SIGVTALRM`208209Виртуальный таймер истек.210211[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.212213#### `signal.SIGWINCH`214215Сигнал изменения размера окна.216217[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.218219#### `signal.SIGXCPU`220221Превышен лимит процессорного времени.222223[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.224225#### `SIG*`226227Все номера сигналов определены символически. Например, сигнал сброса определен как [`signal.SIGHUP`](https://python-all.ru/3.15/library/signal.html#signal.SIGHUP); имена переменных идентичны именам, используемым в программах на C, как в `<signal.h>`. В man-странице Unix для ‘`signal`’ перечислены существующие сигналы (в некоторых системах это *[signal(2)](https://python-all.ru/3.15/library/signal.html)*, в других список находится в *[signal(7)](https://python-all.ru/3.15/library/signal.html)*). Обратите внимание, что не все системы определяют одинаковый набор имен сигналов; только те имена, которые определены системой, определены в этом модуле.228229#### `signal.CTRL_C_EVENT`230231Сигнал, соответствующий комбинации клавиш `Ctrl`+`C`. Этот сигнал может использоваться только с [`os.kill()`](https://python-all.ru/3.15/library/os.html#os.kill).232233[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Windows.234235Добавлено в версии 3.2.236237#### `signal.CTRL_BREAK_EVENT`238239Сигнал, соответствующий комбинации клавиш `Ctrl`+`Break`. Этот сигнал может использоваться только с [`os.kill()`](https://python-all.ru/3.15/library/os.html#os.kill).240241[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Windows.242243Добавлено в версии 3.2.244245#### `signal.NSIG`246247На единицу больше самого высокого номера сигнала. Используйте [`valid_signals()`](https://python-all.ru/3.15/library/signal.html#signal.valid_signals) для получения допустимых номеров сигналов.248249#### `signal.ITIMER_REAL`250251Уменьшает интервальный таймер в реальном времени и отправляет [`SIGALRM`](https://python-all.ru/3.15/library/signal.html#signal.SIGALRM) по истечении.252253#### `signal.ITIMER_VIRTUAL`254255Уменьшает интервальный таймер только во время выполнения процесса и отправляет SIGVTALRM по истечении.256257#### `signal.ITIMER_PROF`258259Уменьшает интервальный таймер как при выполнении процесса, так и при выполнении системой от имени процесса. В паре с ITIMER\_VIRTUAL этот таймер обычно используется для профилирования времени, затраченного приложением в пользовательском и ядерном пространстве. SIGPROF доставляется по истечении времени.260261#### `signal.SIG_BLOCK`262263Возможное значение параметра *how* функции [`pthread_sigmask()`](https://python-all.ru/3.15/library/signal.html#signal.pthread_sigmask), указывающее, что сигналы должны быть заблокированы.264265Добавлено в версии 3.3.266267#### `signal.SIG_UNBLOCK`268269Возможное значение параметра *how* функции [`pthread_sigmask()`](https://python-all.ru/3.15/library/signal.html#signal.pthread_sigmask), указывающее, что сигналы должны быть разблокированы.270271Добавлено в версии 3.3.272273#### `signal.SIG_SETMASK`274275Возможное значение параметра *how* функции [`pthread_sigmask()`](https://python-all.ru/3.15/library/signal.html#signal.pthread_sigmask), указывающее, что маска сигналов должна быть заменена.276277Добавлено в версии 3.3.278279Модуль `signal` определяет одно исключение:280281#### `exception signal.ItimerError`282283Возбуждается для указания на ошибку в реализации [`setitimer()`](https://python-all.ru/3.15/library/signal.html#signal.setitimer) или [`getitimer()`](https://python-all.ru/3.15/library/signal.html#signal.getitimer). Этого исключения следует ожидать, если некорректный интервальный таймер или отрицательное время передаются в `setitimer()`. Это исключение является подтипом [`OSError`](https://python-all.ru/3.15/library/exceptions.html#OSError).284285Добавлено в версии 3.3: Ранее это исключение было подтипом [`IOError`](https://python-all.ru/3.15/library/exceptions.html#IOError), который теперь является псевдонимом [`OSError`](https://python-all.ru/3.15/library/exceptions.html#OSError).286287Модуль `signal` определяет следующие функции:288289#### `signal.alarm(time)`290291Если *time* не равен нулю, эта функция запрашивает отправку сигнала [`SIGALRM`](https://python-all.ru/3.15/library/signal.html#signal.SIGALRM) процессу через *time* секунд. Любой ранее запланированный сигнал отменяется (в любой момент может быть запланирован только один сигнал). Возвращаемое значение – количество секунд до отправки предыдущего запланированного сигнала. Если *time* равно нулю, никакой сигнал не планируется, а любой запланированный отменяется. Если возвращаемое значение равно нулю, сигнал в настоящее время не запланирован.292293[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.294295Для получения дополнительной информации см. справочную страницу *[alarm(2)](https://python-all.ru/3.15/library/signal.html)*.296297#### `signal.getsignal(signalnum)`298299Возвращает текущий обработчик сигнала *signalnum*. Возвращаемое значение может быть вызываемым объектом Python или одним из специальных значений [`signal.SIG_IGN`](https://python-all.ru/3.15/library/signal.html#signal.SIG_IGN), [`signal.SIG_DFL`](https://python-all.ru/3.15/library/signal.html#signal.SIG_DFL) или [`None`](https://python-all.ru/3.15/library/constants.html#None). Здесь `signal.SIG_IGN` означает, что сигнал ранее игнорировался, `signal.SIG_DFL` означает, что ранее использовался способ обработки сигнала по умолчанию, а `None` означает, что предыдущий обработчик сигнала не был установлен из Python.300301#### `signal.strsignal(signalnum)`302303Возвращает описание сигнала *signalnum*, например «Interrupt» для [`SIGINT`](https://python-all.ru/3.15/library/signal.html#signal.SIGINT). Возвращает [`None`](https://python-all.ru/3.15/library/constants.html#None), если *signalnum* не имеет описания. Возбуждает [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError), если *signalnum* недопустим.304305Добавлено в версии 3.8.306307#### `signal.valid_signals()`308309Возвращает набор допустимых номеров сигналов на этой платформе. Он может быть меньше `range(1, NSIG)`, если некоторые сигналы зарезервированы системой для внутреннего использования.310311Добавлено в версии 3.8.312313#### `signal.pause()`314315Приостанавливает выполнение процесса до получения сигнала; затем будет вызван соответствующий обработчик. Ничего не возвращает.316317[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.318319Для получения дополнительной информации см. справочную страницу *[signal(2)](https://python-all.ru/3.15/library/signal.html)*.320321См. также [`sigwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigwait), [`sigwaitinfo()`](https://python-all.ru/3.15/library/signal.html#signal.sigwaitinfo), [`sigtimedwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigtimedwait) и [`sigpending()`](https://python-all.ru/3.15/library/signal.html#signal.sigpending).322323#### `signal.raise_signal(signum)`324325Отправляет сигнал вызывающему процессу. Ничего не возвращает.326327Добавлено в версии 3.8.328329#### `signal.pidfd_send_signal(pidfd, sig, siginfo=None, flags=0)`330331Отправляет сигнал *sig* процессу, на который указывает файловый дескриптор *pidfd*. В настоящее время Python не поддерживает параметр *siginfo*; он должен быть равен `None`. Аргумент *flags* предусмотрен для будущих расширений; в настоящее время не определено никаких значений флагов.332333За дополнительной информацией обращайтесь к справочной странице *[pidfd\_send\_signal(2)](https://python-all.ru/3.15/library/signal.html)*.334335[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Linux \>= 5.1, Android \>= [`build-time`](https://python-all.ru/3.15/library/sys.html#sys.getandroidapilevel) API level 31336337Добавлено в версии 3.9.338339#### `signal.pthread_kill(thread_id, signalnum)`340341Отправляет сигнал *signalnum* потоку *thread\_id*, другому потоку в том же процессе, что и вызывающий. Целевой поток может выполнять любой код (Python или нет). Однако если целевой поток выполняет интерпретатор Python, обработчики сигналов Python будут [выполнены главным потоком главного интерпретатора](https://python-all.ru/3.15/library/signal.html#signals-and-threads). Следовательно, единственный смысл отправки сигнала конкретному потоку Python – принудительно завершить выполняющийся системный вызов с ошибкой [`InterruptedError`](https://python-all.ru/3.15/library/exceptions.html#InterruptedError).342343Используйте [`threading.get_ident()`](https://python-all.ru/3.15/library/threading.html#threading.get_ident) или атрибут [`ident`](https://python-all.ru/3.15/library/threading.html#threading.Thread.ident) объектов [`threading.Thread`](https://python-all.ru/3.15/library/threading.html#threading.Thread), чтобы получить подходящее значение для *thread\_id*.344345Если *signalnum* равен 0, сигнал не отправляется, но проверка ошибок по-прежнему выполняется; это можно использовать для проверки, работает ли целевой поток.346347Возбуждает [событие аудита](https://python-all.ru/3.15/library/sys.html#auditing) `signal.pthread_kill` с аргументами `thread_id`, `signalnum`.348349[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.350351Смотрите man-страницу *[pthread\_kill(3)](https://python-all.ru/3.15/library/signal.html)* для получения дополнительной информации.352353См. также [`os.kill()`](https://python-all.ru/3.15/library/os.html#os.kill).354355Добавлено в версии 3.3.356357#### `signal.pthread_sigmask(how, mask)`358359Получает и/или изменяет маску сигналов вызывающего потока. Маска сигналов – это набор сигналов, доставка которых в настоящий момент заблокирована для вызывающей стороны. Возвращает старую маску сигналов в виде набора сигналов.360361Поведение вызова зависит от значения *how* следующим образом.362363- [`SIG_BLOCK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_BLOCK): Набор заблокированных сигналов – это объединение текущего набора и аргумента *mask*.364- [`SIG_UNBLOCK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_UNBLOCK): Сигналы из *mask* удаляются из текущего набора заблокированных сигналов. Допускается попытка разблокировать сигнал, который не был заблокирован.365- [`SIG_SETMASK`](https://python-all.ru/3.15/library/signal.html#signal.SIG_SETMASK): Набор заблокированных сигналов устанавливается равным аргументу *mask*.366367*mask* – это набор номеров сигналов (например, {[`signal.SIGINT`](https://python-all.ru/3.15/library/signal.html#signal.SIGINT), [`signal.SIGTERM`](https://python-all.ru/3.15/library/signal.html#signal.SIGTERM)}). Используйте [`valid_signals()`](https://python-all.ru/3.15/library/signal.html#signal.valid_signals) для полной маски, включающей все сигналы.368369Например, `signal.pthread_sigmask(signal.SIG_BLOCK, [])` считывает маску сигналов вызывающего потока.370371[`SIGKILL`](https://python-all.ru/3.15/library/signal.html#signal.SIGKILL) и [`SIGSTOP`](https://python-all.ru/3.15/library/signal.html#signal.SIGSTOP) не могут быть заблокированы.372373[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.374375Смотрите man-страницу *[sigprocmask(2)](https://python-all.ru/3.15/library/signal.html)* и *[pthread\_sigmask(3)](https://python-all.ru/3.15/library/signal.html)* для получения дополнительной информации.376377См. также [`pause()`](https://python-all.ru/3.15/library/signal.html#signal.pause), [`sigpending()`](https://python-all.ru/3.15/library/signal.html#signal.sigpending) и [`sigwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigwait).378379Добавлено в версии 3.3.380381#### `signal.setitimer(which, seconds, interval=0)`382383Устанавливает указанный интервальный таймер (один из [`signal.ITIMER_REAL`](https://python-all.ru/3.15/library/signal.html#signal.ITIMER_REAL), [`signal.ITIMER_VIRTUAL`](https://python-all.ru/3.15/library/signal.html#signal.ITIMER_VIRTUAL) или [`signal.ITIMER_PROF`](https://python-all.ru/3.15/library/signal.html#signal.ITIMER_PROF)), определяемый *which*, так чтобы он срабатывал через *seconds* (с округлением до микросекунд, в отличие от [`alarm()`](https://python-all.ru/3.15/library/signal.html#signal.alarm)), а затем каждые *interval* секунд (если *interval* не равен нулю). Интервальный таймер, заданный параметром *which*, можно сбросить, установив *seconds* в ноль.384385Когда срабатывает интервальный таймер, процессу отправляется сигнал. Отправляемый сигнал зависит от используемого таймера: [`signal.ITIMER_REAL`](https://python-all.ru/3.15/library/signal.html#signal.ITIMER_REAL) доставляет [`SIGALRM`](https://python-all.ru/3.15/library/signal.html#signal.SIGALRM), [`signal.ITIMER_VIRTUAL`](https://python-all.ru/3.15/library/signal.html#signal.ITIMER_VIRTUAL) отправляет [`SIGVTALRM`](https://python-all.ru/3.15/library/signal.html#signal.SIGVTALRM), а [`signal.ITIMER_PROF`](https://python-all.ru/3.15/library/signal.html#signal.ITIMER_PROF) доставляет [`SIGPROF`](https://python-all.ru/3.15/library/signal.html#signal.SIGPROF).386387Старые значения возвращаются в виде кортежа из двух чисел с плавающей запятой: (`delay`, `interval`).388389Попытка передать недопустимый интервальный таймер приведет к [`ItimerError`](https://python-all.ru/3.15/library/signal.html#signal.ItimerError).390391[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.392393Изменено в версии 3.15: Принимает любые вещественные числа в качестве *seconds* и *interval*, а не только целые числа или числа с плавающей запятой.394395#### `signal.getitimer(which)`396397Возвращает текущее значение заданного интервального таймера, указанного параметром *which*.398399[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.400401#### `signal.set_wakeup_fd(fd, *, warn_on_full_buffer=True)`402403Устанавливает файловый дескриптор пробуждения в *fd*. Когда получен сигнал, для которого программа зарегистрировала обработчик, номер сигнала записывается одним байтом в этот fd. Если для интересующих сигналов не зарегистрирован обработчик, то в fd пробуждения ничего не записывается. Это может использоваться библиотекой для пробуждения вызова poll или select, что позволяет полностью обработать сигнал.404405Возвращается старый fd пробуждения (или -1, если пробуждение через файловый дескриптор не было включено). Если *fd* равен -1, пробуждение через файловый дескриптор отключается. Если не -1, то *fd* должен быть неблокирующим. Задача библиотеки – удалить все байты из *fd* перед повторным вызовом poll или select.406407Если потоки включены, эту функцию можно вызывать только из [главного потока главного интерпретатора](https://python-all.ru/3.15/library/signal.html#signals-and-threads); попытка вызвать её из других потоков приведёт к возбуждению исключения [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError).408409Существует два распространенных способа использования этой функции. В обоих подходах используется fd для пробуждения при поступлении сигнала, но затем они различаются тем, как определяют, *which* сигнал или сигналы поступили.410411В первом подходе данные читаются из буфера fd, и значения байтов дают номера сигналов. Это просто, но в редких случаях может возникнуть проблема: обычно fd имеет ограниченный объём буфера, и если слишком много сигналов приходит слишком быстро, буфер может переполниться, и некоторые сигналы могут быть потеряны. Если используется этот подход, следует установить `warn_on_full_buffer=True`, что, по крайней мере, приведет к выводу предупреждения в stderr при потере сигналов.412413Во втором подходе fd пробуждения используется *only* для пробуждения, а фактические значения байтов игнорируются. В этом случае важно лишь то, пуст буфер fd или нет; полный буфер не свидетельствует о проблеме. Если используется этот подход, следует установить `warn_on_full_buffer=False`, чтобы пользователи не сбивались с толку ложными предупреждениями.414415Изменено в версии 3.5: В Windows функция теперь также поддерживает дескрипторы сокетов.416417Изменено в версии 3.7: Добавлен параметр `warn_on_full_buffer`.418419#### `signal.siginterrupt(signalnum, flag)`420421Изменяет поведение перезапуска системных вызовов: если *flag* равен [`False`](https://python-all.ru/3.15/library/constants.html#False), системные вызовы будут перезапускаться при прерывании сигналом *signalnum*, в противном случае системные вызовы будут прерваны. Ничего не возвращает.422423[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.424425За дополнительной информацией обращайтесь к man-странице *[siginterrupt(3)](https://python-all.ru/3.15/library/signal.html)*.426427Обратите внимание, что установка обработчика сигнала с помощью [`signal()`](https://python-all.ru/3.15/library/signal.html#module-signal) сбрасывает поведение перезапуска на прерываемое, неявно вызывая `siginterrupt()` со значением *flag*, равным true, для данного сигнала.428429#### `signal.signal(signalnum, handler)`430431Устанавливает обработчик для сигнала *signalnum* в функцию *handler*. *handler* может быть вызываемым объектом Python, принимающим два аргумента (см. ниже), или одним из специальных значений [`signal.SIG_IGN`](https://python-all.ru/3.15/library/signal.html#signal.SIG_IGN) или [`signal.SIG_DFL`](https://python-all.ru/3.15/library/signal.html#signal.SIG_DFL). Возвращается предыдущий обработчик сигнала (см. описание [`getsignal()`](https://python-all.ru/3.15/library/signal.html#signal.getsignal) выше). (За дополнительной информацией обращайтесь к man-странице Unix *[signal(2)](https://python-all.ru/3.15/library/signal.html)*.)432433Если потоки включены, эту функцию можно вызывать только из [главного потока главного интерпретатора](https://python-all.ru/3.15/library/signal.html#signals-and-threads); попытка вызвать её из других потоков приведёт к возбуждению исключения [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError).434435*handler* вызывается с двумя аргументами: номером сигнала и текущим стековым кадром (`None` или объектом кадра; описание объектов кадра см. в [описании в иерархии типов](https://python-all.ru/3.15/reference/datamodel.html#frame-objects) или в описаниях атрибутов модуля [`inspect`](https://python-all.ru/3.15/library/inspect.html#module-inspect)).436437В Windows `signal()` можно вызывать только с [`SIGABRT`](https://python-all.ru/3.15/library/signal.html#signal.SIGABRT), [`SIGFPE`](https://python-all.ru/3.15/library/signal.html#signal.SIGFPE), [`SIGILL`](https://python-all.ru/3.15/library/signal.html#signal.SIGILL), [`SIGINT`](https://python-all.ru/3.15/library/signal.html#signal.SIGINT), [`SIGSEGV`](https://python-all.ru/3.15/library/signal.html#signal.SIGSEGV), [`SIGTERM`](https://python-all.ru/3.15/library/signal.html#signal.SIGTERM) или [`SIGBREAK`](https://python-all.ru/3.15/library/signal.html#signal.SIGBREAK). В любом другом случае будет возбуждено [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError). Обратите внимание, что не все системы определяют одинаковый набор имён сигналов; [`AttributeError`](https://python-all.ru/3.15/library/exceptions.html#AttributeError) будет возбуждено, если имя сигнала не определено как константа уровня модуля `SIG*`.438439#### `signal.sigpending()`440441Проверяет набор сигналов, ожидающих доставки вызывающему потоку (т.е. сигналы, которые были подняты, пока были заблокированы). Возвращает набор ожидающих сигналов.442443[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.444445За дополнительной информацией обращайтесь к man-странице *[sigpending(2)](https://python-all.ru/3.15/library/signal.html)*.446447См. также [`pause()`](https://python-all.ru/3.15/library/signal.html#signal.pause), [`pthread_sigmask()`](https://python-all.ru/3.15/library/signal.html#signal.pthread_sigmask) и [`sigwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigwait).448449Добавлено в версии 3.3.450451#### `signal.sigwait(sigset)`452453Приостанавливает выполнение вызывающего потока до доставки одного из сигналов, указанных в наборе сигналов *sigset*. Функция принимает сигнал (удаляет его из списка ожидающих сигналов) и возвращает номер сигнала.454455[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.456457За дополнительной информацией обращайтесь к man-странице *[sigwait(3)](https://python-all.ru/3.15/library/signal.html)*.458459См. также [`pause()`](https://python-all.ru/3.15/library/signal.html#signal.pause), [`pthread_sigmask()`](https://python-all.ru/3.15/library/signal.html#signal.pthread_sigmask), [`sigpending()`](https://python-all.ru/3.15/library/signal.html#signal.sigpending), [`sigwaitinfo()`](https://python-all.ru/3.15/library/signal.html#signal.sigwaitinfo) и [`sigtimedwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigtimedwait).460461Добавлено в версии 3.3.462463#### `signal.sigwaitinfo(sigset)`464465Приостанавливает выполнение вызывающего потока до доставки одного из сигналов, указанных в наборе сигналов *sigset*. Функция принимает сигнал и удаляет его из списка ожидающих сигналов. Если один из сигналов в *sigset* уже ожидает вызывающий поток, функция немедленно вернётся с информацией об этом сигнале. Обработчик сигнала не вызывается для доставленного сигнала. Функция возбуждает [`InterruptedError`](https://python-all.ru/3.15/library/exceptions.html#InterruptedError), если она была прервана сигналом, которого нет в *sigset*.466467Возвращаемое значение – это объект, представляющий данные, содержащиеся в структуре `siginfo_t`, а именно: `si_signo`, `si_code`, `si_errno`, `si_pid`, `si_uid`, `si_status`, `si_band`.468469[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.470471За дополнительной информацией обращайтесь к man-странице *[sigwaitinfo(2)](https://python-all.ru/3.15/library/signal.html)*.472473См. также [`pause()`](https://python-all.ru/3.15/library/signal.html#signal.pause), [`sigwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigwait) и [`sigtimedwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigtimedwait).474475Добавлено в версии 3.3.476477Изменено в версии 3.5: Теперь функция повторяется, если прервана сигналом, не входящим в *sigset*, и обработчик сигнала не возбуждает исключение (см. [**PEP 475**](https://python-all.ru/3.15/library/signal.html) для обоснования).478479#### `signal.sigtimedwait(sigset, timeout)`480481Как [`sigwaitinfo()`](https://python-all.ru/3.15/library/signal.html#signal.sigwaitinfo), но принимает дополнительный аргумент *timeout*, указывающий тайм-аут. Если *timeout* указан как `0`, выполняется опрос. Возвращает [`None`](https://python-all.ru/3.15/library/constants.html#None) при наступлении тайм-аута.482483[Доступность](https://python-all.ru/3.15/library/intro.html#availability): Unix.484485За дополнительной информацией обращайтесь к man-странице *[sigtimedwait(2)](https://python-all.ru/3.15/library/signal.html)*.486487См. также [`pause()`](https://python-all.ru/3.15/library/signal.html#signal.pause), [`sigwait()`](https://python-all.ru/3.15/library/signal.html#signal.sigwait) и [`sigwaitinfo()`](https://python-all.ru/3.15/library/signal.html#signal.sigwaitinfo).488489Добавлено в версии 3.3.490491Изменено в версии 3.5: Теперь функция повторяется с пересчитанным *timeout*, если прервана сигналом, не входящим в *sigset*, и обработчик сигнала не возбуждает исключение (см. [**PEP 475**](https://python-all.ru/3.15/library/signal.html) для обоснования).492493Изменено в версии 3.15: Принимает любое вещественное число в качестве *timeout*, а не только целое число или число с плавающей точкой.494495## Примеры496497Вот минимальный пример программы. Она использует функцию [`alarm()`](https://python-all.ru/3.15/library/signal.html#signal.alarm) для ограничения времени, затрачиваемого на ожидание открытия файла; это полезно, если файл находится на последовательном устройстве, которое может быть выключено, что обычно приводит к бесконечному зависанию [`os.open()`](https://python-all.ru/3.15/library/os.html#os.open). Решение – установить 5-секундный будильник перед открытием файла; если операция занимает слишком много времени, будет отправлен сигнал будильника, и обработчик возбудит исключение.498499```python500import signal, os501502def handler(signum, frame):503 signame = signal.Signals(signum).name504 print(f'Signal handler called with signal {signame} ({signum})')505 raise OSError("Couldn't open device!")506507# Установить обработчик сигнала и 5-секундный будильник508signal.signal(signal.SIGALRM, handler)509signal.alarm(5)510511# Этот вызов open() может зависнуть навсегда512fd = os.open('/dev/ttyS0', os.O_RDWR)513514signal.alarm(0) # Отключить будильник515```516517## Примечание о SIGPIPE518519Перенаправление вывода программы через конвейер в такие утилиты, как *[head(1)](https://python-all.ru/3.15/library/signal.html)*, приводит к отправке сигнала [`SIGPIPE`](https://python-all.ru/3.15/library/signal.html#signal.SIGPIPE) процессу, когда получатель его стандартного вывода закрывается рано. Это вызывает исключение, подобное `BrokenPipeError: [Errno 32] Broken pipe`. Для обработки этого случая точку входа следует обернуть для перехвата этого исключения следующим образом:520521```python522import os523import sys524525def main():526 try:527 # имитировать большой объем вывода (ваш код заменяет этот цикл)528 for x in range(10000):529 print("y")530 # сбросить вывод здесь, чтобы принудительно вызвать SIGPIPE531 # пока внутри этого блока try.532 sys.stdout.flush()533 except BrokenPipeError:534 # Python сбрасывает стандартные потоки при выходе; перенаправьте оставшийся вывод в /dev/null, чтобы избежать ещё одного BrokenPipeError при завершении работы.535 # в devnull, чтобы избежать еще одного BrokenPipeError при завершении536 devnull = os.open(os.devnull, os.O_WRONLY)537 os.dup2(devnull, sys.stdout.fileno())538 sys.exit(1) # Python завершается с кодом ошибки 1 при EPIPE539540if __name__ == '__main__':541 main()542```543544Не следует устанавливать для [`SIGPIPE`](https://python-all.ru/3.15/library/signal.html#signal.SIGPIPE) действие [`SIG_DFL`](https://python-all.ru/3.15/library/signal.html#signal.SIG_DFL), чтобы избежать [`BrokenPipeError`](https://python-all.ru/3.15/library/exceptions.html#BrokenPipeError). Это приведёт к неожиданному завершению программы всякий раз, когда любое сокетное соединение будет прервано, пока программа ещё пишет в него.545546## Примечание об обработчиках сигналов и исключениях547548Если обработчик сигнала возбуждает исключение, оно будет распространено на главный поток и может быть возбуждено после любой инструкции [байт-кода](https://python-all.ru/3.15/glossary.html#term-bytecode). В первую очередь, [`KeyboardInterrupt`](https://python-all.ru/3.15/library/exceptions.html#KeyboardInterrupt) может появиться в любой точке выполнения. Большая часть кода Python, включая стандартную библиотеку, не может быть сделана устойчивой против этого, поэтому `KeyboardInterrupt` (или любое другое исключение, возникшее в результате работы обработчика сигнала) может в редких случаях перевести программу в непредвиденное состояние.549550Чтобы проиллюстрировать эту проблему, рассмотрим следующий код:551552```python553class SpamContext:554 def __init__(self):555 self.lock = threading.Lock()556557 def __enter__(self):558 # Если KeyboardInterrupt возникает здесь, все в порядке559 self.lock.acquire()560 # Если KeyboardInterrupt возникает здесь, __exit__ не будет вызван561 ...562 # KeyboardInterrupt может возникнуть прямо перед возвратом функции563564 def __exit__(self, exc_type, exc_val, exc_tb):565 ...566 self.lock.release()567```568569Для многих программ, особенно тех, которые просто хотят завершиться по [`KeyboardInterrupt`](https://python-all.ru/3.15/library/exceptions.html#KeyboardInterrupt), это не является проблемой, но приложения, которые являются сложными или требуют высокой надёжности, должны избегать возбуждения исключений в обработчиках сигналов. Им также следует избегать перехвата `KeyboardInterrupt` как способа корректного завершения. Вместо этого они должны установить собственный обработчик [`SIGINT`](https://python-all.ru/3.15/library/signal.html#signal.SIGINT). Ниже приведён пример HTTP-сервера, который избегает `KeyboardInterrupt`:570571```python572import signal573import socket574from selectors import DefaultSelector, EVENT_READ575from http.server import HTTPServer, SimpleHTTPRequestHandler576577interrupt_read, interrupt_write = socket.socketpair()578579def handler(signum, frame):580 print('Signal handler called with signal', signum)581 interrupt_write.send(b'\0')582signal.signal(signal.SIGINT, handler)583584def serve_forever(httpd):585 sel = DefaultSelector()586 sel.register(interrupt_read, EVENT_READ)587 sel.register(httpd, EVENT_READ)588589 while True:590 for key, _ in sel.select():591 if key.fileobj == interrupt_read:592 interrupt_read.recv(1)593 return594 if key.fileobj == httpd:595 httpd.handle_request()596597print("Serving on port 8000")598httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)599serve_forever(httpd)600print("Shutdown...")601```602