signal
— Set handlers for asynchronous events¶
Цей модуль надає механізми для використання обробників сигналів у Python.
Загальні правила¶
Функція signal.signal()
дозволяє визначати спеціальні обробники, які будуть виконуватися під час отримання сигналу. Встановлено невелику кількість обробників за замовчуванням: SIGPIPE
ігнорується (тому про помилки запису в каналах і сокетах можна повідомляти як про звичайні винятки Python), а SIGINT
перетворюється на KeyboardInterrupt
виняток, якщо батьківський процес не змінив його.
Обробник для певного сигналу після встановлення залишається встановленим, доки його явно не буде скинуто (Python емулює інтерфейс у стилі BSD незалежно від базової реалізації), за винятком обробника для SIGCHLD
, який слідує за базовою реалізацією. .
Виконання обробників сигналів Python¶
Обробник сигналу Python не виконується всередині обробника сигналу низького рівня (C). Натомість обробник сигналу низького рівня встановлює прапорець, який повідомляє virtual machine виконати відповідний обробник сигналу Python пізніше (наприклад, у наступній інструкції bytecode). Це має наслідки:
Немає сенсу виловлювати синхронні помилки, такі як
SIGFPE
абоSIGSEGV
, які викликані недійсною операцією в коді C. Python повернеться від обробника сигналів до коду C, який, імовірно, знову викличе той самий сигнал, що, очевидно, призведе до зависання Python. Починаючи з Python 3.3, ви можете використовувати модульfaulthandler
для звітування про синхронні помилки.Тривале обчислення, реалізоване виключно на C (наприклад, зіставлення регулярного виразу з великою частиною тексту), може виконуватися безперервно протягом довільного проміжку часу, незалежно від будь-яких отриманих сигналів. Обробники сигналів Python будуть викликані, коли обчислення завершиться.
Сигнали та нитки¶
Python signal handlers are always executed in the main Python thread,
even if the signal was received in another thread. This means that signals
can’t be used as a means of inter-thread communication. You can use
the synchronization primitives from the threading
module instead.
Besides, only the main thread is allowed to set a new signal handler.
Зміст модуля¶
Змінено в версії 3.5: signal (SIG*), handler (SIG_DFL
, SIG_IGN
) and sigmask
(SIG_BLOCK
, SIG_UNBLOCK
, SIG_SETMASK
)
related constants listed below were turned into
enums
.
getsignal()
, pthread_sigmask()
, sigpending()
and
sigwait()
functions return human-readable
enums
.
Змінні, визначені в модулі signal
:
-
signal.
SIG_DFL
¶ Це один із двох стандартних варіантів обробки сигналу; він просто виконуватиме стандартну функцію для сигналу. Наприклад, у більшості систем дія за замовчуванням для
SIGQUIT
— це дамп ядра та вихід, а дія за замовчуванням дляSIGCHLD
— просто ігнорувати його.
-
signal.
SIG_IGN
¶ Це ще один стандартний обробник сигналу, який просто ігнорує поданий сигнал.
-
signal.
SIGFPE
¶ Виняток із плаваючою комою. Наприклад, ділення на нуль.
Дивись також
ZeroDivisionError
виникає, коли другий аргумент операції ділення або модуля дорівнює нулю.
-
signal.
SIGHUP
¶ Виявлено зависання на керуючому терміналі або смерть керуючого процесу.
Наявність: Unix.
-
signal.
SIGILL
¶ Незаконна інструкція.
-
signal.
SIGINT
¶ Переривання з клавіатури (CTRL + C).
Дія за замовчуванням — підняти
KeyboardInterrupt
.
-
signal.
SIGKILL
¶ Сигнал вбивства.
Його неможливо зловити, заблокувати чи проігнорувати.
Наявність: Unix.
-
signal.
SIGPIPE
¶ Зламаний канал: записувати в канал без читачів.
Стандартна дія – ігнорувати сигнал.
Наявність: Unix.
-
signal.
SIGSEGV
¶ Помилка сегментації: недійсне посилання на пам’ять.
-
signal.
SIGTERM
¶ Сигнал завершення.
-
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
¶ One more than the number of the highest signal number.
-
signal.
ITIMER_REAL
¶ Зменшує інтервальний таймер у реальному часі та доставляє
SIGALRM
після закінчення терміну дії.
-
signal.
ITIMER_VIRTUAL
¶ Зменшує інтервальний таймер, лише коли процес виконується, і доставляє SIGVTALRM після закінчення терміну дії.
-
signal.
ITIMER_PROF
¶ Зменшує інтервальний таймер як під час виконання процесу, так і коли система виконується від імені процесу. У поєднанні з ITIMER_VIRTUAL цей таймер зазвичай використовується для профілювання часу, проведеного програмою в просторі користувача та ядра. SIGPROF доставляється після закінчення терміну дії.
-
signal.
SIG_BLOCK
¶ Можливе значення для параметра how для
pthread_sigmask()
, яке вказує, що сигнали мають бути заблоковані.Нове в версії 3.3.
-
signal.
SIG_UNBLOCK
¶ Можливе значення для параметра how для
pthread_sigmask()
, яке вказує, що сигнали мають бути розблоковані.Нове в версії 3.3.
-
signal.
SIG_SETMASK
¶ Можливе значення для параметра how для
pthread_sigmask()
, яке вказує, що маску сигналу потрібно замінити.Нове в версії 3.3.
Модуль signal
визначає один виняток:
-
exception
signal.
ItimerError
¶ Викликається, щоб повідомити про помилку базової реалізації
setitimer()
абоgetitimer()
. Очікуйте цю помилку, якщо вsetitimer()
передано недійсний таймер інтервалу або від’ємний час. Ця помилка є підтипомOSError
.
Модуль signal
визначає такі функції:
-
signal.
alarm
(time)¶ Якщо time не нуль, ця функція запитує, щоб сигнал
SIGALRM
був надісланий процесу через time секунди. Будь-який раніше запланований будильник скасовується (одночасно можна запланувати лише один будильник). Повернене значення – це кількість секунд до того, як будь-який попередньо встановлений сигнал буде доставлено. Якщо time дорівнює нулю, будильник не заплановано, а будь-який запланований будильник скасовується. Якщо повернене значення дорівнює нулю, нагадування наразі не заплановано.Availability: Unix. See the man page alarm(2) for further information.
-
signal.
getsignal
(signalnum)¶ Повертає поточний обробник сигналу для сигналу signalnum. Поверненим значенням може бути об’єкт Python, який можна викликати, або одне зі спеціальних значень
signal.SIG_IGN
,signal.SIG_DFL
абоNone
. Тутsignal.SIG_IGN
означає, що сигнал раніше ігнорувався,signal.SIG_DFL
означає, що стандартний спосіб обробки сигналу використовувався раніше, аNone
означає, що попередній обробник сигналів не було встановлено з Python.
-
signal.
strsignal
(signalnum)¶ Return the system description of the signal signalnum, such as «Interrupt», «Segmentation fault», etc. Returns
None
if the signal is not recognized.Нове в версії 3.8.
-
signal.
valid_signals
()¶ Повернути набір дійсних номерів сигналу на цій платформі. Це може бути менше ніж діапазон (1, NSIG) якщо деякі сигнали зарезервовані системою для внутрішнього використання.
Нове в версії 3.8.
-
signal.
pause
()¶ Перевести процес у режим сну, доки не буде отримано сигнал; потім буде викликано відповідний обробник. Нічого не повертає.
Availability: Unix. See the man page signal(2) for further information.
Дивіться також
sigwait()
,sigwaitinfo()
,sigtimedwait()
іsigpending()
.
-
signal.
raise_signal
(signum)¶ Надсилає сигнал процесу виклику. Нічого не повертає.
Нове в версії 3.8.
-
signal.
pthread_kill
(thread_id, signalnum)¶ Send the signal signalnum to the thread thread_id, another thread in the same process as the caller. The target thread can be executing any code (Python or not). However, if the target thread is executing the Python interpreter, the Python signal handlers will be executed by the main thread. Therefore, the only point of sending a signal to a particular Python thread would be to force a running system call to fail with
InterruptedError
.Use
threading.get_ident()
or theident
attribute ofthreading.Thread
objects to get a suitable value for thread_id.Якщо signalnum дорівнює 0, тоді сигнал не надсилається, але перевірка помилок все одно виконується; це можна використовувати, щоб перевірити, чи цільовий потік все ще працює.
Викликає подію аудиту
signal.pthread_kill
з аргументамиthread_id
,signalnum
.Availability: Unix. See the man page pthread_kill(3) for further information.
Дивіться також
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
не можна заблокувати.Availability: Unix. See the man page sigprocmask(3) and pthread_sigmask(3) for further information.
Дивіться також
pause()
,sigpending()
іsigwait()
.Нове в версії 3.3.
-
signal.
setitimer
(which, seconds, interval=0.0)¶ Встановлює заданий інтервальний таймер (один із
signal.ITIMER_REAL
,signal.ITIMER_VIRTUAL
абоsignal.ITIMER_PROF
), визначений який запускати через секунд (дозволено число, відмінний відalarm()
) і після цього кожні інтервал секунд (якщо інтервал відмінний від нуля). Інтервальний таймер, визначений яким, можна скинути, встановивши секунд на нуль.Коли спрацьовує інтервальний таймер, процесу надсилається сигнал. Надісланий сигнал залежить від таймера, який використовується;
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. Це може бути використано бібліотекою для пробудження опитування або виклику вибору, дозволяючи повністю обробити сигнал.
Повертається старий fd пробудження (або -1, якщо пробудження дескриптора файлу не було ввімкнено). Якщо fd дорівнює -1, пробудження дескриптора файлу вимкнено. Якщо не -1, fd має бути неблокуючим. Бібліотека має видалити будь-які байти з fd перед повторним викликом опитування або вибору.
When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a
ValueError
exception to be raised.Існує два поширених способи використання цієї функції. В обох підходах ви використовуєте 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, інакше системні виклики буде перервано. Нічого не повертає.Availability: Unix. See the man page siginterrupt(3) for further information.
Note that installing a signal handler with
signal()
will reset the restart behaviour to interruptible by implicitly callingsiginterrupt()
with a true flag value for the given signal.
-
signal.
signal
(signalnum, handler)¶ Встановіть обробник для сигналу signalnum на функцію handler. обробник може бути викликаним об’єктом Python, який приймає два аргументи (див. нижче) або одне зі спеціальних значень
signal.SIG_IGN
абоsignal.SIG_DFL
. Буде повернено попередній обробник сигналу (див. описgetsignal()
вище). (Див. сторінку довідки Unix signal(2) для отримання додаткової інформації.)When threads are enabled, this function can only be called from the main thread; attempting to call it from other threads will cause a
ValueError
exception to be raised.Обробник викликається з двома аргументами: номером сигналу та поточним фреймом стека (
None
або об’єкт фрейму; для опису об’єктів фрейму див. опис в ієрархії типів або див. описи атрибутів у модуліinspect
).У Windows
signal()
можна викликати лише за допомогоюSIGABRT
,SIGFPE
,SIGILL
,SIGINT
,SIGSEGV
,SIGTERM
абоSIGBREAK
. ПомилкаValueError
буде викликана в будь-якому іншому випадку. Зауважте, що не всі системи визначають однаковий набір назв сигналів;AttributeError
буде викликано, якщо назва сигналу не визначена як константа рівня модуляSIG*
.
-
signal.
sigpending
()¶ Перевірте набір сигналів, які очікують на доставку до викликаючого потоку (тобто сигнали, які були підняті під час блокування). Повертає набір незавершених сигналів.
Availability: Unix. See the man page sigpending(2) for further information.
Дивіться також
pause()
,pthread_sigmask()
іsigwait()
.Нове в версії 3.3.
-
signal.
sigwait
(sigset)¶ Призупинити виконання викликаючого потоку до доставки одного із сигналів, указаних у наборі сигналів sigset. Функція приймає сигнал (видаляє його зі списку очікуваних сигналів) і повертає номер сигналу.
Availability: Unix. See the man page sigwait(3) for further information.
Дивіться також
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
.Availability: Unix. See the man page sigwaitinfo(2) for further information.
Дивіться також
pause()
,sigwait()
іsigtimedwait()
.Нове в версії 3.3.
Змінено в версії 3.5: Тепер функція виконується повторно, якщо її перериває сигнал не в sigset, і обробник сигналу не викликає винятку (див. PEP 475 для обґрунтування).
-
signal.
sigtimedwait
(sigset, timeout)¶ Like
sigwaitinfo()
, but takes an additional timeout argument specifying a timeout. If timeout is specified as0
, a poll is performed. ReturnsNone
if a timeout occurs.Availability: Unix. See the man page sigtimedwait(2) for further information.
Дивіться також
pause()
,sigwait()
іsigwaitinfo()
.Нове в версії 3.3.
Змінено в версії 3.5: Тепер функція виконується повторно з повторно обчисленим тайм-аутом, якщо її перериває сигнал не в sigset, і обробник сигналу не викликає виняткової ситуації (див. PEP 475 для обґрунтування).
Example¶
Ось мінімальний приклад програми. Він використовує функцію 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()
Do not set SIGPIPE
’s disposition to SIG_DFL
in order to avoid BrokenPipeError
. Doing that would cause
your program to exit unexpectedly also whenever any socket connection
is interrupted while your program is still writing to it.