twisted: поймать прерывание клавиатуры и правильно завершить работу

ОБНОВЛЕНИЕ: Для удобства чтения вот как добавить обратный вызов до того, как реактор отключится:

reactor.addSystemEventTrigger('before', 'shutdown', callable)

Далее следует исходный вопрос.


Если у меня есть клиент, подключенный к серверу, и это пугает в главном цикле реактора, ожидающем событий, когда я нажимаю CTRL-C, я получаю «Соединение с другой стороной было потеряно не чистым способом: Соединение потеряно». Как я могу настроить его так, чтобы я знал, когда происходит KeyboardInterrupt, так что я могу сделать правильную очистку и чисто отключиться? Или как я могу реализовать более чистый способ завершения работы, не использующий CTRL-C, если это возможно?

17
задан Claudiu 6 November 2013 в 07:58
поделиться

2 ответа

Если вы действительно хотите специально поймать Cc, вы можете сделать это обычным способом для приложения Python - используйте signal.signal , чтобы установить обработчик для SIGINT это делает все, что вы хотите. Если вы вызываете какие-либо Twisted API из обработчика, убедитесь, что вы используете response.callFromThread , поскольку почти все другие Twisted API небезопасны для вызова из обработчиков сигналов.

Однако, если вас действительно интересует вставка кода очистки времени выключения, то вы, вероятно, захотите использовать IService.stopService (или механизм, в рамках которого он реализован, response.addSystemEventTrigger ) вместо этого.

Если вы используете twistd , тогда использовать IService.stopService несложно. У вас уже есть объект Приложение , к которому прикреплена хотя бы одна служба. Вы можете добавить еще один с помощью специального метода stopService , который выполняет вашу работу по завершению работы. Метод может возвращать Deferred . Если это так, то процесс выключения приостанавливается до тех пор, пока не сработает Deferred . Это позволяет вам аккуратно очистить ваши соединения, даже если это связано с некоторыми дополнительными сетевыми (или любыми другими асинхронными) операциями.

Если вы не используете twistd , то, вероятно, проще напрямую использовать response.addSystemEventTrigger . Вы можете установить триггер перед выключением , который будет вызываться в тех же обстоятельствах, когда был бы вызван IService.stopService .Этот триггер (как и любой вызываемый объект) также может возвращать Deferred для задержки завершения работы. Это делается с помощью вызова response.addSystemEventTrigger ('before', 'shutdown', callable) (незадолго до того, как будет инициировано выключение, так что он уже регистрируется всякий раз, когда выключение действительно происходит).

service.tac дает пример создания и использования настраиваемой службы.

wxacceptance.py дает пример использования addSystemEventTrigger и задержки выключения на (произвольные) три секунды.

Оба этих механизма будут сообщать вам всякий раз, когда реактор останавливается. Это может быть связано с нажатием клавиши C-c, или это может быть потому, что кто-то использовал kill -INT ... , или это может быть потому, что где-то был вызван response.stop () . Все они приводят к останову реактора, а останов реактора всегда приводит к возникновению триггеров события останова.

30
ответ дан 30 November 2019 в 12:26
поделиться

Я не уверен, говорите ли вы о клиенте или сервере, который вы написано.

В любом случае, с «CTRL-C» все в порядке.

Если вы пишете сервер как приложение. Подкласс из twisted.application.service.Service и определение startService и stopService . Поддерживайте список активных экземпляров протокола. Используйте stopService , чтобы просмотреть их и корректно закрыть.

Если у вас есть клиент, вы также можете создать подкласс Service , но было бы проще использовать response.addSystemEventTrigger ('before', 'shutdown', myCleanUpFunction) , и изящно закрыть соединение (я) в этой функции.

1
ответ дан 30 November 2019 в 12:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: