Рубрики
Без рубрики

Получение сигналов Unix

Автор оригинала: Doug Hellmann.

Уведомления о мероприятиях системы Unix обычно прерывают приложение, вызывая свой обработчик. При использовании с ASYNCIO обратные вызовы обработчиков сигналов чередуются с другими COROUTINES и обратными обратными вызовами, управляемыми контуром события. Это приводит к меньшему количеству прерванных функций, и в результате необходимость обеспечить безопасную охранников для очистки неполных операций.

Обработчики сигналов должны быть регулярными каплями, а не COROUTINES.

asyncio_signal.py

import asyncio
import functools
import os
import signal


def signal_handler(name):
    print('signal_handler({!r})'.format(name))

Обработчики сигналов зарегистрированы с использованием ADD_SIGNAL_HANDLER () . Первый аргумент – это сигнал, а второй – обратный вызов. Обратные обратные вызовы не передаются аргументам, поэтому, если аргументы нужны функция, функция может быть завернута <код> funcctools.partial () .

event_loop  asyncio.get_event_loop()

event_loop.add_signal_handler(
    signal.SIGHUP,
    functools.partial(signal_handler, name'SIGHUP'),
)
event_loop.add_signal_handler(
    signal.SIGUSR1,
    functools.partial(signal_handler, name'SIGUSR1'),
)
event_loop.add_signal_handler(
    signal.SIGINT,
    functools.partial(signal_handler, name'SIGINT'),
)

Этот пример программы использует COROUTINE для отправки сигналов для себя через OS.KILL () . После того, как каждый сигнал отправляется, COROUTINE дает контроль, чтобы позволить обработчику работать. В нормальном применении было бы больше мест, где код приложения дает обратно на петлю событий, и не требуется, чтобы искусственный доход не понадобится.

async def send_signals():
    pid  os.getpid()
    print('starting send_signals for {}'.format(pid))

    for name in ['SIGHUP', 'SIGHUP', 'SIGUSR1', 'SIGINT']:
        print('sending {}'.format(name))
        os.kill(pid, getattr(signal, name))
        # Yield control to allow the signal handler to run,
        # since the signal does not interrupt the program
        # flow otherwise.
        print('yielding control')
        await asyncio.sleep(0.01)
    return

Основная программа работает <код> send_signals () до тех пор, пока не отправит все сигналы.

try:
    event_loop.run_until_complete(send_signals())
finally:
    event_loop.close()

Выходной вывод показывает, как обработчики вызываются при SEND_Signals () дают контроль после отправки сигнала.

$ python3 asyncio_signal.py

starting send_signals for 21772
sending SIGHUP
yielding control
signal_handler('SIGHUP')
sending SIGHUP
yielding control
signal_handler('SIGHUP')
sending SIGUSR1
yielding control
signal_handler('SIGUSR1')
sending SIGINT
yielding control
signal_handler('SIGINT')

Смотрите также

  • Сигнал – получение уведомления асинхронных системных событий