python – 为什么没有捕获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()上,我启动了CherryPy的线程化实例.我创建了一个线程,认为可能是因为CherryPy正在运行,主线程没有看到Ctrl C.这似乎没有任何影响,但发布代码,因为我现在拥有它:
__主要__:
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中放置了一个断点,它永远不会被击中.
解决方法:
目前还不太清楚你想要达到的目标,但看起来你错过了CherryPy设计的重点.
CherryPy状态和组件编排是在the message bus左右构建的.作为开发人员,它也是特定于操作系统的信令的抽象.因此,如果你想拥有一个线程,最好将其包含到CherryPy plugin中,这将遵循服务器的状态.
#!/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 e.g. 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)
UPDATE
更明确地说明了处理SIGINT信号.这是第一个链接的FSM图.
O
|
V
STOPPING --> STOPPED --> EXITING -> X
A A |
| \___ |
| \ |
| V V
STARTED <-- STARTING
您的兴趣是停止或退出,因为两者都与处理SIGINT有关.不同之处在于STOPPING可能会发生几次,例如当服务器被守护时,SIGHUP使它重新启动.所以你可以把你的终止例程放在ExamplePlugin.exit中.
标签:python,cherrypy,sigint 来源: https://codeday.me/bug/20191003/1846765.html