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

signal.md

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

1> **Источник:** https://python-all.ru/3.2/library/signal.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 17.4. [`signal`](https://python-all.ru/3.2/library/signal.html#module-signal) – Установка обработчиков асинхронных событий89Этот модуль предоставляет механизмы для использования обработчиков сигналов в Python.1011## 17.4.1. Общие правила1213Функция [`signal.signal()`](https://python-all.ru/3.2/library/signal.html#signal.signal) позволяет определять пользовательские обработчики, которые выполняются при получении сигнала. Установлено небольшое количество обработчиков по умолчанию: `SIGPIPE` игнорируется (так что ошибки записи в каналы и сокеты могут сообщаться как обычные исключения Python), а `SIGINT` преобразуется в исключение [`KeyboardInterrupt`](https://python-all.ru/3.2/library/exceptions.html#KeyboardInterrupt).1415Обработчик конкретного сигнала после установки остаётся активным, пока его явно не сбросят (Python эмулирует интерфейс в стиле BSD независимо от базовой реализации), за исключением обработчика `SIGCHLD`, который следует базовой реализации.1617Нет способа временно «блокировать» сигналы в критических секциях (поскольку это поддерживается не во всех разновидностях Unix).1819### 17.4.1.1. Выполнение обработчиков сигналов Python2021Обработчик сигналов Python не выполняется внутри низкоуровневого (C) обработчика сигналов. Вместо этого низкоуровневый обработчик устанавливает флаг, который сообщает [*виртуальной машине*](https://python-all.ru/3.2/glossary.html#term-virtual-machine) выполнить соответствующий обработчик Python позже (например, на следующей инструкции [*байткода*](https://python-all.ru/3.2/glossary.html#term-bytecode)). Это имеет последствия:2223- Мало смысла ловить синхронные ошибки вроде `SIGFPE` или `SIGSEGV`.24- Длительное вычисление, реализованное чисто на C (например, сравнение с регулярным выражением по большому объему текста), может выполняться без прерывания сколь угодно долго, независимо от полученных сигналов. Обработчики сигналов Python будут вызваны по завершении вычисления.2526### 17.4.1.2. Сигналы и потоки2728Обработчики сигналов Python всегда выполняются в главном потоке Python, даже если сигнал был получен в другом потоке. Это означает, что сигналы нельзя использовать как средство межпоточного взаимодействия. Вместо этого можно использовать примитивы синхронизации из модуля [`threading`](https://python-all.ru/3.2/library/threading.html#module-threading).2930Кроме того, только главный поток может устанавливать новый обработчик сигнала.3132## 17.4.2. Содержимое модуля3334Переменные, определённые в модуле [`signal`](https://python-all.ru/3.2/library/signal.html#module-signal):3536#### `signal.SIG_DFL`3738Это один из двух стандартных вариантов обработки сигналов; он просто выполняет действие по умолчанию для сигнала. Например, на большинстве систем действие по умолчанию для `SIGQUIT` – сбросить дамп ядра и завершиться, а для `SIGCHLD` – просто игнорировать его.3940#### `signal.SIG_IGN`4142Это еще один стандартный обработчик сигнала, который просто игнорирует данный сигнал.4344#### `SIG*`4546Все номера сигналов определены символически. Например, сигнал отбоя (hangup) определён как `signal.SIGHUP`; имена переменных совпадают с именами, используемыми в программах на C, как в `<signal.h>`. Страница руководства Unix для ‘`signal()`‘ содержит список существующих сигналов (в некоторых системах это *signal(2)*, в других список находится в *signal(7)*). Обратите внимание, что не все системы определяют один и тот же набор имён сигналов; этот модуль определяет только те имена, которые определены системой.4748#### `signal.CTRL_C_EVENT`4950Сигнал, соответствующий событию нажатия клавиш CTRL+C. Этот сигнал можно использовать только с [`os.kill()`](https://python-all.ru/3.2/library/os.html#os.kill).5152Доступность: Windows.5354Новое в версии 3.2.5556#### `signal.CTRL_BREAK_EVENT`5758Сигнал, соответствующий событию нажатия клавиш CTRL+BREAK. Этот сигнал можно использовать только с [`os.kill()`](https://python-all.ru/3.2/library/os.html#os.kill).5960Доступность: Windows.6162Новое в версии 3.2.6364#### `signal.NSIG`6566На единицу больше номера самого высокого сигнала.6768#### `signal.ITIMER_REAL`6970Уменьшает интервальный таймер в реальном времени и отправляет `SIGALRM` по истечении.7172#### `signal.ITIMER_VIRTUAL`7374Уменьшает интервальный таймер только во время выполнения процесса и отправляет SIGVTALRM по истечении.7576#### `signal.ITIMER_PROF`7778Уменьшает интервальный таймер как при выполнении процесса, так и при выполнении системой от имени процесса. В паре с ITIMER\_VIRTUAL этот таймер обычно используется для профилирования времени, затраченного приложением в пользовательском и ядерном пространстве. SIGPROF доставляется по истечении времени.7980Модуль [`signal`](https://python-all.ru/3.2/library/signal.html#module-signal) определяет одно исключение:8182#### `exception signal.ItimerError`8384Возбуждается для сообщения об ошибке в реализации [`setitimer()`](https://python-all.ru/3.2/library/signal.html#signal.setitimer) или [`getitimer()`](https://python-all.ru/3.2/library/signal.html#signal.getitimer). Ожидайте эту ошибку, если в [`setitimer()`](https://python-all.ru/3.2/library/signal.html#signal.setitimer) передан недопустимый интервальный таймер или отрицательное время. Эта ошибка является подтипом [`IOError`](https://python-all.ru/3.2/library/exceptions.html#IOError).8586Модуль [`signal`](https://python-all.ru/3.2/library/signal.html#module-signal) определяет следующие функции:8788#### `signal.alarm(time)`8990Если *time* не равно нулю, эта функция запрашивает отправку сигнала `SIGALRM` процессу через *time* секунд. Любой ранее запланированный сигнал отменяется (в любой момент времени может быть запланирован только один сигнал). Возвращаемое значение – количество секунд до момента, когда должен был быть доставлен любой ранее установленный сигнал. Если *time* равно нулю, сигнал не планируется, а любой запланированный отменяется. Если возвращаемое значение равно нулю, сигнал в данный момент не запланирован. (См. man-страницу Unix *alarm(2)*.) Доступность: Unix.9192#### `signal.getsignal(signalnum)`9394Возвращает текущий обработчик сигнала для сигнала *signalnum*. Возвращаемое значение может быть вызываемым объектом Python или одним из специальных значений: [`signal.SIG_IGN`](https://python-all.ru/3.2/library/signal.html#signal.SIG_IGN), [`signal.SIG_DFL`](https://python-all.ru/3.2/library/signal.html#signal.SIG_DFL) или [`None`](https://python-all.ru/3.2/library/constants.html#None). Здесь [`signal.SIG_IGN`](https://python-all.ru/3.2/library/signal.html#signal.SIG_IGN) означает, что сигнал ранее игнорировался, [`signal.SIG_DFL`](https://python-all.ru/3.2/library/signal.html#signal.SIG_DFL) означает, что ранее использовался способ обработки сигнала по умолчанию, а `None` означает, что предыдущий обработчик сигнала не был установлен из Python.9596#### `signal.pause()`9798Заставляет процесс спать до получения сигнала; затем будет вызван соответствующий обработчик. Ничего не возвращает. Недоступно в Windows. (См. страницу руководства Unix *signal(2)*.)99100#### `signal.setitimer(which, seconds[, interval])`101102Устанавливает заданный интервальный таймер (один из [`signal.ITIMER_REAL`](https://python-all.ru/3.2/library/signal.html#signal.ITIMER_REAL), [`signal.ITIMER_VIRTUAL`](https://python-all.ru/3.2/library/signal.html#signal.ITIMER_VIRTUAL) или [`signal.ITIMER_PROF`](https://python-all.ru/3.2/library/signal.html#signal.ITIMER_PROF)), указанный *which*, чтобы он сработал через *seconds* (принимается число с плавающей запятой, в отличие от [`alarm()`](https://python-all.ru/3.2/library/signal.html#signal.alarm)) и после этого каждые *interval* секунд. Интервальный таймер, указанный *which*, можно сбросить, установив seconds в ноль.103104Когда интервальный таймер срабатывает, процессу отправляется сигнал. Отправляемый сигнал зависит от используемого таймера; [`signal.ITIMER_REAL`](https://python-all.ru/3.2/library/signal.html#signal.ITIMER_REAL) доставляет `SIGALRM`, [`signal.ITIMER_VIRTUAL`](https://python-all.ru/3.2/library/signal.html#signal.ITIMER_VIRTUAL) отправляет `SIGVTALRM`, а [`signal.ITIMER_PROF`](https://python-all.ru/3.2/library/signal.html#signal.ITIMER_PROF) доставляет `SIGPROF`.105106Старые значения возвращаются в виде кортежа: (delay, interval).107108Попытка передать недопустимый интервальный таймер вызовет [`ItimerError`](https://python-all.ru/3.2/library/signal.html#signal.ItimerError). Доступность: Unix.109110#### `signal.getitimer(which)`111112Возвращает текущее значение указанного интервального таймера, заданного через *which*. Доступность: Unix.113114#### `signal.set_wakeup_fd(fd)`115116Устанавливает fd пробуждения в *fd*. Когда получен сигнал, в fd записывается один `'\0'` байт. Это может использоваться библиотекой для пробуждения вызова poll или select, чтобы сигнал был полностью обработан.117118Возвращается старый дескриптор пробуждения. *fd* должен быть неблокирующим. Библиотека должна удалить все байты перед повторным вызовом poll или select.119120Когда потоки включены, эту функцию можно вызывать только из основного потока; попытка вызова из других потоков приведёт к возникновению исключения [`ValueError`](https://python-all.ru/3.2/library/exceptions.html#ValueError).121122#### `signal.siginterrupt(signalnum, flag)`123124Изменяет поведение перезапуска системных вызовов: если *flag* равно [`False`](https://python-all.ru/3.2/library/constants.html#False), системные вызовы будут перезапущены при прерывании сигналом *signalnum*, в противном случае системные вызовы будут прерваны. Ничего не возвращает. Доступность: Unix (см. man-страницу *siginterrupt(3)* для получения дополнительной информации).125126Обратите внимание, что установка обработчика сигнала с помощью [`signal()`](https://python-all.ru/3.2/library/signal.html#module-signal) сбросит поведение перезапуска на прерываемое, неявно вызывая `siginterrupt()` со значением *flag*, равным true, для данного сигнала.127128#### `signal.signal(signalnum, handler)`129130Устанавливает обработчик сигнала *signalnum* как функцию *handler*. *handler* может быть вызываемым объектом Python, принимающим два аргумента (см. ниже), или одним из специальных значений [`signal.SIG_IGN`](https://python-all.ru/3.2/library/signal.html#signal.SIG_IGN) или [`signal.SIG_DFL`](https://python-all.ru/3.2/library/signal.html#signal.SIG_DFL). Ранее установленный обработчик сигнала будет возвращён (см. описание [`getsignal()`](https://python-all.ru/3.2/library/signal.html#signal.getsignal) выше). (См. страницу руководства Unix *signal(2)*.)131132Когда потоки включены, эту функцию можно вызывать только из основного потока; попытка вызова из других потоков приведёт к возникновению исключения [`ValueError`](https://python-all.ru/3.2/library/exceptions.html#ValueError).133134*handler* вызывается с двумя аргументами: номером сигнала и текущим стековым кадром (`None` или объект кадра; описание объектов кадра см. в [*описании иерархии типов*](https://python-all.ru/3.2/reference/datamodel.html#frame-objects) или в описаниях атрибутов в модуле [`inspect`](https://python-all.ru/3.2/library/inspect.html#module-inspect)).135136В Windows [`signal()`](https://python-all.ru/3.2/library/signal.html#module-signal) можно вызывать только с `SIGABRT`, `SIGFPE`, `SIGILL`, `SIGINT`, `SIGSEGV` или `SIGTERM`. В любом другом случае будет вызвано [`ValueError`](https://python-all.ru/3.2/library/exceptions.html#ValueError).137138## 17.4.3. Пример139140Вот минимальный пример программы. В ней используется функция [`alarm()`](https://python-all.ru/3.2/library/signal.html#signal.alarm) для ограничения времени ожидания открытия файла; это полезно, если файл относится к последовательному устройству, которое может быть выключено, и обычно это приводит к тому, что [`os.open()`](https://python-all.ru/3.2/library/os.html#os.open) зависает на неопределённый срок. Решение – установить 5-секундный будильник перед открытием файла; если операция займёт слишком много времени, будет отправлен сигнал будильника, и обработчик вызовет исключение.141142```python143import signal, os144145def handler(signum, frame):146    print('Signal handler called with signal', signum)147    raise IOError("Couldn't open device!")148149# Установить обработчик сигнала и 5-секундный будильник150signal.signal(signal.SIGALRM, handler)151signal.alarm(5)152153# Этот вызов open() может зависнуть навсегда154fd = os.open('/dev/ttyS0', os.O_RDWR)155156signal.alarm(0)          # Отключить будильник157```158