ОБНОВЛЕНИЕ: Для удобства чтения вот как добавить обратный вызов до того, как реактор отключится:
reactor.addSystemEventTrigger('before', 'shutdown', callable)
Далее следует исходный вопрос.
Если у меня есть клиент, подключенный к серверу, и это пугает в главном цикле реактора, ожидающем событий, когда я нажимаю CTRL-C, я получаю «Соединение с другой стороной было потеряно не чистым способом: Соединение потеряно». Как я могу настроить его так, чтобы я знал, когда происходит KeyboardInterrupt, так что я могу сделать правильную очистку и чисто отключиться? Или как я могу реализовать более чистый способ завершения работы, не использующий CTRL-C, если это возможно?
Если вы действительно хотите специально поймать 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 ()
. Все они приводят к останову реактора, а останов реактора всегда приводит к возникновению триггеров события останова.
Я не уверен, говорите ли вы о клиенте или сервере, который вы написано.
В любом случае, с «CTRL-C» все в порядке.
Если вы пишете сервер как приложение. Подкласс из twisted.application.service.Service
и определение startService
и stopService
. Поддерживайте список активных экземпляров протокола. Используйте stopService
, чтобы просмотреть их и корректно закрыть.
Если у вас есть клиент, вы также можете создать подкласс Service
, но было бы проще использовать response.addSystemEventTrigger ('before', 'shutdown', myCleanUpFunction)
, и изящно закрыть соединение (я) в этой функции.