Документация Python неофициальный перевод

signal.md

266 строк · 31.7 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.6/library/signal.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.8. [`signal`](https://python-all.ru/3.6/library/signal.html#module-signal) – Установка обработчиков для асинхронных событий89---1011Этот модуль предоставляет механизмы для использования обработчиков сигналов в Python.1213## 18.8.1. Общие правила1415Функция [`signal.signal()`](https://python-all.ru/3.6/library/signal.html#signal.signal) позволяет определять пользовательские обработчики, которые выполняются при получении сигнала. Установлено небольшое количество обработчиков по умолчанию: `SIGPIPE` игнорируется (поэтому ошибки записи в каналы и сокеты могут сообщаться как обычные исключения Python), а `SIGINT` преобразуется в исключение [`KeyboardInterrupt`](https://python-all.ru/3.6/library/exceptions.html#KeyboardInterrupt).1617Обработчик конкретного сигнала после установки остается активным до явной переустановки (Python эмулирует интерфейс в стиле BSD независимо от реализации), за исключением обработчика для `SIGCHLD`, который следует базовой реализации.1819### 18.8.1.1. Выполнение обработчиков сигналов Python2021Обработчик сигналов Python не выполняется внутри низкоуровневого (C) обработчика сигналов. Вместо этого низкоуровневый обработчик устанавливает флаг, который сообщает [виртуальной машине](https://python-all.ru/3.6/glossary.html#term-virtual-machine) выполнить соответствующий обработчик Python позже (например, на следующей инструкции [байткода](https://python-all.ru/3.6/glossary.html#term-bytecode)). Это имеет последствия:2223- Ловить синхронные ошибки вроде `SIGFPE` или `SIGSEGV`, вызванные недопустимой операцией в коде C, не имеет смысла. Python вернется от обработчика сигнала к коду C, который, скорее всего, снова возбудит тот же сигнал, что приведет к зависанию Python. Начиная с Python 3.3 можно использовать модуль [`faulthandler`](https://python-all.ru/3.6/library/faulthandler.html#module-faulthandler) для сообщения о синхронных ошибках.24- Длительное вычисление, реализованное чисто на C (например, сравнение с регулярным выражением по большому объему текста), может выполняться без прерывания сколь угодно долго, независимо от полученных сигналов. Обработчики сигналов Python будут вызваны по завершении вычисления.2526### 18.8.1.2. Сигналы и потоки2728Обработчики сигналов Python всегда выполняются в главном потоке Python, даже если сигнал был получен в другом потоке. Это означает, что сигналы нельзя использовать для межпоточной коммуникации. Вместо этого можно использовать примитивы синхронизации из модуля [`threading`](https://python-all.ru/3.6/library/threading.html#module-threading).2930Кроме того, только главный поток может устанавливать новый обработчик сигнала.3132## 18.8.2. Содержимое модуля3334Изменено в версии 3.5: signal (SIG\*), handler ([`SIG_DFL`](https://python-all.ru/3.6/library/signal.html#signal.SIG_DFL), [`SIG_IGN`](https://python-all.ru/3.6/library/signal.html#signal.SIG_IGN)) и sigmask ([`SIG_BLOCK`](https://python-all.ru/3.6/library/signal.html#signal.SIG_BLOCK), [`SIG_UNBLOCK`](https://python-all.ru/3.6/library/signal.html#signal.SIG_UNBLOCK), [`SIG_SETMASK`](https://python-all.ru/3.6/library/signal.html#signal.SIG_SETMASK)) и перечисленные ниже константы были преобразованы в [`enums`](https://python-all.ru/3.6/library/enum.html#enum.IntEnum). Функции [`getsignal()`](https://python-all.ru/3.6/library/signal.html#signal.getsignal), [`pthread_sigmask()`](https://python-all.ru/3.6/library/signal.html#signal.pthread_sigmask), [`sigpending()`](https://python-all.ru/3.6/library/signal.html#signal.sigpending) и [`sigwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigwait) возвращают человекочитаемые [`enums`](https://python-all.ru/3.6/library/enum.html#enum.IntEnum).3536Переменные, определенные в модуле [`signal`](https://python-all.ru/3.6/library/signal.html#module-signal):3738#### `signal.SIG_DFL`3940Это один из двух стандартных вариантов обработки сигналов; он просто выполняет функцию по умолчанию для сигнала. Например, на большинстве систем действие по умолчанию для `SIGQUIT` – сбросить дамп ядра и завершиться, тогда как действие по умолчанию для `SIGCHLD` – просто игнорировать его.4142#### `signal.SIG_IGN`4344Это еще один стандартный обработчик сигнала, который просто игнорирует данный сигнал.4546#### `SIG*`4748Все номера сигналов определены символически. Например, сигнал разъединения (hangup) определяется как `signal.SIGHUP`; имена переменных совпадают с именами, используемыми в программах на C, которые можно найти в `<signal.h>`. Страница руководства Unix для «`signal()`» перечисляет существующие сигналы (в некоторых системах это *signal(2)*, в других список находится в *signal(7)*). Обратите внимание, что не все системы определяют один и тот же набор имен сигналов; модуль определяет только те имена, которые определены системой.4950#### `signal.CTRL_C_EVENT`5152Сигнал, соответствующий нажатию клавиши `Ctrl+C`. Этот сигнал можно использовать только с [`os.kill()`](https://python-all.ru/3.6/library/os.html#os.kill).5354Доступность: Windows.5556Новое в версии 3.2.5758#### `signal.CTRL_BREAK_EVENT`5960Сигнал, соответствующий нажатию клавиши `Ctrl+Break`. Этот сигнал можно использовать только с [`os.kill()`](https://python-all.ru/3.6/library/os.html#os.kill).6162Доступность: Windows.6364Новое в версии 3.2.6566#### `signal.NSIG`6768На единицу больше номера самого высокого сигнала.6970#### `signal.ITIMER_REAL`7172Уменьшает интервальный таймер в реальном времени и отправляет `SIGALRM` по истечении.7374#### `signal.ITIMER_VIRTUAL`7576Уменьшает интервальный таймер только во время выполнения процесса и отправляет SIGVTALRM по истечении.7778#### `signal.ITIMER_PROF`7980Уменьшает интервальный таймер как при выполнении процесса, так и при выполнении системой от имени процесса. В паре с ITIMER\_VIRTUAL этот таймер обычно используется для профилирования времени, затраченного приложением в пользовательском и ядерном пространстве. SIGPROF доставляется по истечении времени.8182#### `signal.SIG_BLOCK`8384Возможное значение параметра *how* функции [`pthread_sigmask()`](https://python-all.ru/3.6/library/signal.html#signal.pthread_sigmask), указывающее, что сигналы должны быть заблокированы.8586Новое в версии 3.3.8788#### `signal.SIG_UNBLOCK`8990Возможное значение параметра *how* функции [`pthread_sigmask()`](https://python-all.ru/3.6/library/signal.html#signal.pthread_sigmask), указывающее, что сигналы должны быть разблокированы.9192Новое в версии 3.3.9394#### `signal.SIG_SETMASK`9596Возможное значение параметра *how* функции [`pthread_sigmask()`](https://python-all.ru/3.6/library/signal.html#signal.pthread_sigmask), указывающее, что маска сигналов должна быть заменена.9798Новое в версии 3.3.99100Модуль [`signal`](https://python-all.ru/3.6/library/signal.html#module-signal) определяет одно исключение:101102#### `exception signal.ItimerError`103104Возбуждается для указания на ошибку в реализации [`setitimer()`](https://python-all.ru/3.6/library/signal.html#signal.setitimer) или [`getitimer()`](https://python-all.ru/3.6/library/signal.html#signal.getitimer). Этого исключения следует ожидать, если некорректный интервальный таймер или отрицательное время передаются в [`setitimer()`](https://python-all.ru/3.6/library/signal.html#signal.setitimer). Это исключение является подтипом [`OSError`](https://python-all.ru/3.6/library/exceptions.html#OSError).105106Новое в версии 3.3: Раньше эта ошибка была подтипом [`IOError`](https://python-all.ru/3.6/library/exceptions.html#IOError), который теперь является синонимом [`OSError`](https://python-all.ru/3.6/library/exceptions.html#OSError).107108Модуль [`signal`](https://python-all.ru/3.6/library/signal.html#module-signal) определяет следующие функции:109110#### `signal.alarm(time)`111112Если *time* не равно нулю, эта функция запрашивает отправку сигнала `SIGALRM` процессу через *time* секунд. Любая ранее запланированная тревога отменяется (одновременно может быть запланирована только одна тревога). Возвращаемое значение – количество секунд до момента, когда должна была быть доставлена предыдущая тревога. Если *time* равно нулю, тревога не планируется, а любая запланированная отменяется. Если возвращаемое значение равно нулю, текущая тревога не запланирована. (См. страницу руководства Unix *alarm(2)*.) Доступность: Unix.113114#### `signal.getsignal(signalnum)`115116Возвращает текущий обработчик сигнала *signalnum*. Возвращаемое значение может быть вызываемым объектом Python или одним из специальных значений [`signal.SIG_IGN`](https://python-all.ru/3.6/library/signal.html#signal.SIG_IGN), [`signal.SIG_DFL`](https://python-all.ru/3.6/library/signal.html#signal.SIG_DFL) или [`None`](https://python-all.ru/3.6/library/constants.html#None). Здесь [`signal.SIG_IGN`](https://python-all.ru/3.6/library/signal.html#signal.SIG_IGN) означает, что сигнал ранее игнорировался, [`signal.SIG_DFL`](https://python-all.ru/3.6/library/signal.html#signal.SIG_DFL) означает, что ранее использовался способ обработки сигнала по умолчанию, а `None` означает, что предыдущий обработчик сигнала не был установлен из Python.117118#### `signal.pause()`119120Заставляет процесс спать до получения сигнала; затем будет вызван соответствующий обработчик. Ничего не возвращает. Недоступно в Windows. (См. страницу руководства Unix *signal(2)*.)121122См. также [`sigwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigwait), [`sigwaitinfo()`](https://python-all.ru/3.6/library/signal.html#signal.sigwaitinfo), [`sigtimedwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigtimedwait) и [`sigpending()`](https://python-all.ru/3.6/library/signal.html#signal.sigpending).123124#### `signal.pthread_kill(thread_id, signalnum)`125126Посылает сигнал *signalnum* потоку *thread\_id*, другому потоку в том же процессе, что и вызывающий. Целевой поток может выполнять любой код (Python или нет). Однако, если целевой поток выполняет интерпретатор Python, обработчики сигналов Python будут [выполнены главным потоком](https://python-all.ru/3.6/library/signal.html#signals-and-threads). Следовательно, единственный смысл отправки сигнала конкретному потоку Python – это принудительное завершение работающего системного вызова с ошибкой [`InterruptedError`](https://python-all.ru/3.6/library/exceptions.html#InterruptedError).127128Используйте [`threading.get_ident()`](https://python-all.ru/3.6/library/threading.html#threading.get_ident) или атрибут [`ident`](https://python-all.ru/3.6/library/threading.html#threading.Thread.ident) объектов [`threading.Thread`](https://python-all.ru/3.6/library/threading.html#threading.Thread), чтобы получить подходящее значение для *thread\_id*.129130Если *signalnum* равен 0, сигнал не отправляется, но проверка ошибок по-прежнему выполняется; это можно использовать для проверки, работает ли целевой поток.131132Доступность: Unix (см. страницу руководства *pthread\_kill(3)* для получения дополнительной информации).133134См. также [`os.kill()`](https://python-all.ru/3.6/library/os.html#os.kill).135136Новое в версии 3.3.137138#### `signal.pthread_sigmask(how, mask)`139140Получает и/или изменяет маску сигналов вызывающего потока. Маска сигналов – это набор сигналов, доставка которых в настоящий момент заблокирована для вызывающей стороны. Возвращает старую маску сигналов в виде набора сигналов.141142Поведение вызова зависит от значения *how* следующим образом.143144- [`SIG_BLOCK`](https://python-all.ru/3.6/library/signal.html#signal.SIG_BLOCK): Набор заблокированных сигналов – это объединение текущего набора и аргумента *mask*.145- [`SIG_UNBLOCK`](https://python-all.ru/3.6/library/signal.html#signal.SIG_UNBLOCK): Сигналы из *mask* удаляются из текущего набора заблокированных сигналов. Допускается попытка разблокировать сигнал, который не был заблокирован.146- [`SIG_SETMASK`](https://python-all.ru/3.6/library/signal.html#signal.SIG_SETMASK): Набор заблокированных сигналов устанавливается равным аргументу *mask*.147148*mask* – это множество номеров сигналов (например, {`signal.SIGINT`, `signal.SIGTERM`}). Для полной маски, включающей все сигналы, используйте `range(1, signal.NSIG)`.149150Например, `signal.pthread_sigmask(signal.SIG_BLOCK, [])` считывает маску сигналов вызывающего потока.151152Доступность: Unix. См. страницы руководства *sigprocmask(3)* и *pthread\_sigmask(3)* для получения дополнительной информации.153154См. также [`pause()`](https://python-all.ru/3.6/library/signal.html#signal.pause), [`sigpending()`](https://python-all.ru/3.6/library/signal.html#signal.sigpending) и [`sigwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigwait).155156Новое в версии 3.3.157158#### `signal.setitimer(which, seconds[, interval])`159160Устанавливает заданный интервальный таймер (один из [`signal.ITIMER_REAL`](https://python-all.ru/3.6/library/signal.html#signal.ITIMER_REAL), [`signal.ITIMER_VIRTUAL`](https://python-all.ru/3.6/library/signal.html#signal.ITIMER_VIRTUAL) или [`signal.ITIMER_PROF`](https://python-all.ru/3.6/library/signal.html#signal.ITIMER_PROF)), указанный через *which*, для срабатывания через *seconds* секунд (допускается число с плавающей точкой, в отличие от [`alarm()`](https://python-all.ru/3.6/library/signal.html#signal.alarm)) и затем каждые *interval* секунд. Интервальный таймер, указанный через *which*, можно сбросить, установив seconds в ноль.161162Когда срабатывает интервальный таймер, процессу отправляется сигнал. Отправляемый сигнал зависит от используемого таймера: [`signal.ITIMER_REAL`](https://python-all.ru/3.6/library/signal.html#signal.ITIMER_REAL) доставляет `SIGALRM`, [`signal.ITIMER_VIRTUAL`](https://python-all.ru/3.6/library/signal.html#signal.ITIMER_VIRTUAL) отправляет `SIGVTALRM`, а [`signal.ITIMER_PROF`](https://python-all.ru/3.6/library/signal.html#signal.ITIMER_PROF) доставляет `SIGPROF`.163164Старые значения возвращаются в виде кортежа: (delay, interval).165166Попытка передать недопустимый интервальный таймер вызовет [`ItimerError`](https://python-all.ru/3.6/library/signal.html#signal.ItimerError). Доступность: Unix.167168#### `signal.getitimer(which)`169170Возвращает текущее значение указанного интервального таймера, заданного через *which*. Доступность: Unix.171172#### `signal.set_wakeup_fd(fd)`173174Устанавливает дескриптор файла пробуждения в *fd*. Когда сигнал получен, номер сигнала записывается в fd как один байт. Это может быть использовано библиотекой для пробуждения вызова poll или select, позволяя полностью обработать сигнал.175176Возвращается старый fd пробуждения (или -1, если пробуждение через файловый дескриптор не было включено). Если *fd* равен -1, пробуждение через файловый дескриптор отключается. Если не -1, то *fd* должен быть неблокирующим. Задача библиотеки – удалить все байты из *fd* перед повторным вызовом poll или select.177178Используйте, например, `struct.unpack('%uB' % len(data), data)` для декодирования списка номеров сигналов.179180Когда потоки включены, эту функцию можно вызывать только из главного потока; попытка вызова из других потоков приведет к возникновению исключения [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError).181182Изменено в версии 3.5: В Windows функция теперь также поддерживает дескрипторы сокетов.183184#### `signal.siginterrupt(signalnum, flag)`185186Изменяет поведение перезапуска системных вызовов: если *flag* равно [`False`](https://python-all.ru/3.6/library/constants.html#False), системные вызовы будут перезапущены при прерывании сигналом *signalnum*, в противном случае системные вызовы будут прерваны. Ничего не возвращает. Доступность: Unix (см. страницу руководства *siginterrupt(3)* для получения дополнительной информации).187188Обратите внимание, что установка обработчика сигнала с помощью [`signal()`](https://python-all.ru/3.6/library/signal.html#module-signal) сбрасывает поведение перезапуска на прерываемое, неявно вызывая `siginterrupt()` со значением *flag*, равным true, для данного сигнала.189190#### `signal.signal(signalnum, handler)`191192Устанавливает обработчик для сигнала *signalnum* равным функции *handler*. *handler* может быть вызываемым объектом Python, принимающим два аргумента (см. ниже), или одним из специальных значений [`signal.SIG_IGN`](https://python-all.ru/3.6/library/signal.html#signal.SIG_IGN) или [`signal.SIG_DFL`](https://python-all.ru/3.6/library/signal.html#signal.SIG_DFL). Возвращается предыдущий обработчик сигнала (см. описание [`getsignal()`](https://python-all.ru/3.6/library/signal.html#signal.getsignal) выше). (См. страницу руководства Unix *signal(2)*).193194Когда потоки включены, эту функцию можно вызывать только из главного потока; попытка вызова из других потоков приведет к возникновению исключения [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError).195196*handler* вызывается с двумя аргументами: номером сигнала и текущим стековым кадром (`None` или объектом кадра; описание объектов кадра см. в [описании в иерархии типов](https://python-all.ru/3.6/reference/datamodel.html#frame-objects) или в описаниях атрибутов модуля [`inspect`](https://python-all.ru/3.6/library/inspect.html#module-inspect)).197198В Windows [`signal()`](https://python-all.ru/3.6/library/signal.html#module-signal) можно вызывать только с `SIGABRT`, `SIGFPE`, `SIGILL`, `SIGINT`, `SIGSEGV`, `SIGTERM` или `SIGBREAK`. В любом другом случае будет возбуждено [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError). Обратите внимание, что не все системы определяют одинаковый набор имён сигналов; [`AttributeError`](https://python-all.ru/3.6/library/exceptions.html#AttributeError) будет возбуждено, если имя сигнала не определено как константа уровня модуля `SIG*`.199200#### `signal.sigpending()`201202Проверяет набор сигналов, ожидающих доставки вызывающему потоку (т.е. сигналы, которые были подняты, пока были заблокированы). Возвращает набор ожидающих сигналов.203204Доступность: Unix (см. страницу руководства *sigpending(2)* для получения дополнительной информации).205206См. также [`pause()`](https://python-all.ru/3.6/library/signal.html#signal.pause), [`pthread_sigmask()`](https://python-all.ru/3.6/library/signal.html#signal.pthread_sigmask) и [`sigwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigwait).207208Новое в версии 3.3.209210#### `signal.sigwait(sigset)`211212Приостанавливает выполнение вызывающего потока до доставки одного из сигналов, указанных в наборе сигналов *sigset*. Функция принимает сигнал (удаляет его из списка ожидающих сигналов) и возвращает номер сигнала.213214Доступность: Unix (см. страницу руководства *sigwait(3)* для получения дополнительной информации).215216См. также [`pause()`](https://python-all.ru/3.6/library/signal.html#signal.pause), [`pthread_sigmask()`](https://python-all.ru/3.6/library/signal.html#signal.pthread_sigmask), [`sigpending()`](https://python-all.ru/3.6/library/signal.html#signal.sigpending), [`sigwaitinfo()`](https://python-all.ru/3.6/library/signal.html#signal.sigwaitinfo) и [`sigtimedwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigtimedwait).217218Новое в версии 3.3.219220#### `signal.sigwaitinfo(sigset)`221222Приостанавливает выполнение вызывающего потока до доставки одного из сигналов, указанных в наборе сигналов *sigset*. Функция принимает сигнал и удаляет его из списка ожидающих сигналов. Если один из сигналов в *sigset* уже ожидает вызывающий поток, функция немедленно вернётся с информацией об этом сигнале. Обработчик сигнала не вызывается для доставленного сигнала. Функция возбуждает [`InterruptedError`](https://python-all.ru/3.6/library/exceptions.html#InterruptedError), если она была прервана сигналом, которого нет в *sigset*.223224Возвращаемое значение – объект, представляющий данные, содержащиеся в структуре `siginfo_t`, а именно: `si_signo`, `si_code`, `si_errno`, `si_pid`, `si_uid`, `si_status`, `si_band`.225226Доступность: Unix (см. страницу руководства *sigwaitinfo(2)* для получения дополнительной информации).227228См. также [`pause()`](https://python-all.ru/3.6/library/signal.html#signal.pause), [`sigwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigwait) и [`sigtimedwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigtimedwait).229230Новое в версии 3.3.231232Изменено в версии 3.5: Теперь функция повторяется, если прервана сигналом, не входящим в *sigset*, и обработчик сигнала не возбуждает исключение (см. [**PEP 475**](https://python-all.ru/3.6/library/signal.html) для обоснования).233234#### `signal.sigtimedwait(sigset, timeout)`235236Как [`sigwaitinfo()`](https://python-all.ru/3.6/library/signal.html#signal.sigwaitinfo), но принимает дополнительный аргумент *timeout*, указывающий тайм-аут. Если *timeout* указан как `0`, выполняется опрос. Возвращает [`None`](https://python-all.ru/3.6/library/constants.html#None) при наступлении тайм-аута.237238Доступно: Unix (см. man-страницу *sigtimedwait(2)* для получения дополнительной информации).239240См. также [`pause()`](https://python-all.ru/3.6/library/signal.html#signal.pause), [`sigwait()`](https://python-all.ru/3.6/library/signal.html#signal.sigwait) и [`sigwaitinfo()`](https://python-all.ru/3.6/library/signal.html#signal.sigwaitinfo).241242Новое в версии 3.3.243244Изменено в версии 3.5: Теперь функция повторяется с пересчитанным *timeout*, если прервана сигналом, не входящим в *sigset*, и обработчик сигнала не возбуждает исключение (см. [**PEP 475**](https://python-all.ru/3.6/library/signal.html) для обоснования).245246## 18.8.3. Пример247248Вот минимальный пример программы. Она использует функцию [`alarm()`](https://python-all.ru/3.6/library/signal.html#signal.alarm) для ограничения времени, затрачиваемого на ожидание открытия файла; это полезно, если файл находится на последовательном устройстве, которое может быть выключено, что обычно приводит к бесконечному зависанию [`os.open()`](https://python-all.ru/3.6/library/os.html#os.open). Решение – установить 5-секундный будильник перед открытием файла; если операция занимает слишком много времени, будет отправлен сигнал будильника, и обработчик возбудит исключение.249250```python251import signal, os252253def handler(signum, frame):254    print('Signal handler called with signal', signum)255    raise OSError("Couldn't open device!")256257# Установить обработчик сигнала и 5-секундный будильник258signal.signal(signal.SIGALRM, handler)259signal.alarm(5)260261# Этот вызов open() может зависнуть навсегда262fd = os.open('/dev/ttyS0', os.O_RDWR)263264signal.alarm(0)          # Отключить будильник265```266