Почему CTRL-C не был захвачен и вызван signal_handler?

У меня есть следующая стандартная реализация захвата Ctrl + C :

def signal_handler(signal, frame): status = server.stop() print("[{source}] Server Status: {status}".format(source=__name__.upper(), status=status)) print("Exiting ...") sys.exit(0) signal.signal(signal.SIGINT, signal_handler) 

На server.start() Я server.start() threaded экземпляр CherryPy. Я создал поток, думая, что, возможно, с момента запуска CherryPy, основной поток не видит Ctrl + C. По-видимому, это не повлияло, но опубликовал код, как я его сейчас:

__main__ :

  server.start() 

сервер :

 def start(self): # self.engine references cherrypy.engine self.__cherry_thread = threading.Thread(target=self.engine.start) self.status['running'] = True self.status['start_time'] = get_timestamp() self.__cherry_thread.start() def stop(self): self.status['running'] = False self.status['stop_time'] = get_timestamp() self.engine.exit() self.__thread_event.set() return self.status 

Когда я нажимаю Ctrl + C, приложение не останавливается. Я поставил signal_handler останова в signal_handler выше, и он никогда не попадал.

  • Python: как предотвратить подпроцессы от приема CTRL-C / Control-C / SIGINT
  • Отправка SIGINT (Ctrl-C) для запуска программы в консоли Eclipse
  • Захват SIGINT с использованием исключения KeyboardInterrupt работает в терминале, а не в скрипте
  • Python: вывести команду Ctrl-C. Подсказка «действительно хочу выйти (y / n)», возобновить выполнение, если нет
  • Как остановить передачу SIGINT на подпроцесс в python?
  • One Solution collect form web for “Почему CTRL-C не был захвачен и вызван signal_handler?”

    Не совсем понятно, чего вы хотите достичь в конце, но похоже, что вы пропустили важный момент дизайна CherryPy.

    Состояние и компонентная компоновка CherryPy построены вокруг шины сообщений . Для вас как разработчика это также абстракция от сигнализации, специфичной для ОС. Поэтому, если вы хотите иметь поток, неплохо вписаться в плагин CherryPy, который будет придерживаться состояния сервера.

     #!/usr/bin/env python # -*- coding: utf-8 -*- import threading import time import logging import cherrypy from cherrypy.process.plugins import SimplePlugin config = { 'global' : { 'server.socket_host' : '127.0.0.1', 'server.socket_port' : 8080, 'server.thread_pool' : 8 } } class ExamplePlugin(SimplePlugin): _thread = None _running = None _sleep = None def __init__(self, bus, sleep = 2): SimplePlugin.__init__(self, bus) self._sleep = sleep def start(self): '''Called when the engine starts''' self.bus.log('Setting up example plugin') # You can listen for a message published in request handler or # elsewhere. Usually it's putting some into the queue and waiting # for queue entry in the thread. self.bus.subscribe('do-something', self._do) self._running = True if not self._thread: self._thread = threading.Thread(target = self._target) self._thread.start() # Make sure plugin priority matches your design eg when starting a # thread and using Daemonizer which forks and has priority of 65, you # need to start after the fork as default priority is 50 # see https://groups.google.com/forum/#!topic/cherrypy-users/1fmDXaeCrsA start.priority = 70 def stop(self): '''Called when the engine stops''' self.bus.log('Freeing up example plugin') self.bus.unsubscribe('do-something', self._do) self._running = False if self._thread: self._thread.join() self._thread = None def exit(self): '''Called when the engine exits''' self.unsubscribe() def _target(self): while self._running: try: self.bus.log('some periodic routine') time.sleep(self._sleep) except: self.bus.log('Error in example plugin', level = logging.ERROR, traceback = True) def _do(self, arg): self.bus.log('handling the message: {0}'.format(arg)) class App: @cherrypy.expose def index(self): cherrypy.engine.publish('do-something', 'foo') return 'Look in the terminal or log' if __name__ == '__main__': ExamplePlugin(cherrypy.engine).subscribe() cherrypy.quickstart(App(), '/', config) 

    ОБНОВИТЬ

    Более подробно о обработке сигнала SIGINT. Вот диаграмма FSM из первой ссылки.

      O | V STOPPING --> STOPPED --> EXITING -> X AA | | \___ | | \ | | VV STARTED <-- STARTING 

    Ваш интерес – это STOPPING или EXITING поскольку оба относятся к обработке SIGINT. Разница заключается в том, что STOPPING может возникать несколько раз, например, когда сервер демоннизирован. SIGHUP заставляет его перезагружаться. Поэтому вы можете просто поместить свою процедуру завершения в ExamplePlugin.exit .

    Python - лучший язык программирования в мире.