Почему я не могу поймать SIGINT, когда запущен цикл событий asyncio?

Используя Python 3.4.1 в Windows, я обнаружил, что при выполнении цикла событий asyncio моя программа не может быть прервана ( т.е. нажатием Ctrl + C в терминале). Более того, сигнал SIGINT игнорируется. И наоборот, я решил, что SIGINT обрабатывается, если не в цикле событий.

Почему SIGINT игнорируется при выполнении цикла событий asyncio?

Следующая программа должна продемонстрировать проблему - запустите ее в терминале и попытайтесь остановить ее, нажав Ctrl + C, она должна продолжать работать:

import asyncio
import signal


# Never gets called after entering event loop
def handler(*args):
    print('Signaled')


signal.signal(signal.SIGINT, handler)

print('Event loop starting')
loop = asyncio.SelectorEventLoop()
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')

См. обсуждение в официальном списке рассылки (Tulip).

Ответ 1

Я нашел обходное решение, которое должно планировать периодический обратный вызов. Хотя это работает, SIGINT, по-видимому, обрабатывается:

import asyncio


def wakeup():
    # Call again
    loop.call_later(0.1, wakeup)


print('Event loop starting')
loop = asyncio.SelectorEventLoop()
# Register periodic callback
loop.call_later(0.1, wakeup)
asyncio.set_event_loop(loop)
loop.run_forever()
print('Event loop ended')

Не уверен, почему это необходимо, но это указывает на то, что сигналы блокируются, пока цикл событий ждет событий ( "опросы" ).

Вопрос о обсуждался в официальном списке рассылки (Tulip), мой способ обхода, по-видимому, теперь идет.

Update

Исправление предположительно пробилось в Python 3.5, так что, надеюсь, мое обходное решение будет устаревшим из-за этой версии Python.

Ответ 2

Я обнаружил, что при выполнении цикла событий asyncio моя программа не может быть прервана (т.е. нажав Ctrl + C в терминале)

Чтобы уточнить: ctrl-C может не работать, но ctrl-break работает просто отлично.

Ответ 3

Обычно вы добавляете обратный вызов для них с loop.add_signal_handler(), но, к сожалению, эта функция не поддерживается встроенными циклами событий Windows:/

Можно использовать периодическую проверку, да. В противном случае цикл работает за пределами возможности модуля signal для захвата сигналов.