Python 2.7 通过以下信号停止python 2.7守护进程
我在脚本中使用Python2.7.3和守护进程运行程序。在run(loop)方法中,我希望睡眠一段时间,但不想使用这样的代码:Python 2.7 通过以下信号停止python 2.7守护进程,python-2.7,signals,multiprocessing,daemon,python-daemon,Python 2.7,Signals,Multiprocessing,Daemon,Python Daemon,我在脚本中使用Python2.7.3和守护进程运行程序。在run(loop)方法中,我希望睡眠一段时间,但不想使用这样的代码: while True: time.sleep(10) def handle_exit(self, signum, frame): t = Timer(1, self.handle_exit2) t.start() def handle_exit2(self): self.daemon_context.stop_event.s
while True:
time.sleep(10)
def handle_exit(self, signum, frame):
t = Timer(1, self.handle_exit2)
t.start()
def handle_exit2(self):
self.daemon_context.stop_event.set()
我想等待一些同步原语,例如multiprocessing.Event。这是我的代码:
# -*- coding: utf-8 -*-
import logging
from daemon import runner
import signal
import multiprocessing
import spyder_cfg
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M', filename=spyder_cfg.log_file)
class Daemon(object):
def __init__(self, pidfile_path):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = None
self.pidfile_timeout = 5
self.pidfile_path = pidfile_path
def setup_daemon_context(self, daemon_context):
self.daemon_context = daemon_context
def run(self):
logging.info('Spyder service has started')
logging.debug('event from the run() = {}'.format(self.daemon_context.stop_event))
while not self.daemon_context.stop_event.wait(10):
try:
logging.info('Spyder is working...')
except BaseException as exc:
logging.exception(exc)
logging.info('Spyder service has been stopped')
def handle_exit(self, signum, frame):
try:
logging.info('Spyder stopping...')
self.daemon_context.stop_event.set()
except BaseException as exc:
logging.exception(exc)
if __name__ == '__main__':
app = Daemon(spyder_cfg.pid_file)
d = runner.DaemonRunner(app)
d.daemon_context.working_directory = spyder_cfg.work_dir
d.daemon_context.files_preserve = [h.stream for h in logging.root.handlers]
d.daemon_context.signal_map = {signal.SIGUSR1: app.handle_exit}
d.daemon_context.stop_event = multiprocessing.Event()
app.setup_daemon_context(d.daemon_context)
logging.debug('event from the main = {}'.format(d.daemon_context.stop_event))
d.do_action()
def handle_exit(self, signum, frame):
t = Timer(1, self.handle_exit2)
t.start()
def handle_exit2(self):
self.daemon_context.stop_event.set()
这是我的日志文件记录:
06-04 11:32 root DEBUG event from the main = <multiprocessing.synchronize.Event object at 0x7f0ef0930d50>
06-04 11:32 root INFO Spyder service has started
06-04 11:32 root DEBUG event from the run() = <multiprocessing.synchronize.Event object at 0x7f0ef0930d50>
06-04 11:32 root INFO Spyder is working...
06-04 11:32 root INFO Spyder stopping...
def handle_exit(self, signum, frame):
t = Timer(1, self.handle_exit2)
t.start()
def handle_exit2(self):
self.daemon_context.stop_event.set()
06-04 11:32来自主服务器的根调试事件=
06-04 11:32根信息Spyder服务已启动
06-04 11:32来自运行()的根调试事件
06-04 11:32根信息Spyder正在工作。。。
06-04 11:32根信息Spyder正在停止。。。
日志中没有“Spyder服务已停止”打印,我的程序挂起set()调用。在调试时,我看到它在Event.set()调用时挂起,set方法在所有等待的实体唤醒时挂起信号量。事件是否为全局对象或threading.Event没有理由。我明白了,但这对我不好。是否有另一种等待方式,即超时等待,其行为与多处理.Event相同?我确实从信号处理程序打印堆栈,我认为存在死锁,因为信号处理程序和我的主进程使用相同的堆栈,当我调用堆栈上较高的Event.set()、method wait()时
def handle_exit(self, signum, frame):
try:
logging.debug('Signal handler:{}'.format(traceback.print_stack()))
except BaseException as exc:
logging.exception(exc)
d.do_action()
File ".../venv/work/local/lib/python2.7/site-packages/daemon/runner.py", line 189, in do_action
func(self)
File ".../venv/work/local/lib/python2.7/site-packages/daemon/runner.py", line 134, in _start
self.app.run()
File ".../venv/work/skelet/src/spyder.py", line 32, in run
while not self.daemon_context.stop_event.wait(10):
File "/usr/lib/python2.7/multiprocessing/synchronize.py", line 337, in wait
self._cond.wait(timeout)
File "/usr/lib/python2.7/multiprocessing/synchronize.py", line 246, in wait
self._wait_semaphore.acquire(True, timeout)
File ".../venv/work/skelet/src/spyder.py", line 41, in handle_exit
logging.debug('Signal handler:{}'.format(traceback.print_stack()))
def handle_exit(self, signum, frame):
t = Timer(1, self.handle_exit2)
t.start()
def handle_exit2(self):
self.daemon_context.stop_event.set()
这就是此修复程序解决问题的原因:
def handle_exit(self, signum, frame):
t = Timer(1, self.handle_exit2)
t.start()
def handle_exit2(self):
self.daemon_context.stop_event.set()
这是修复我的代码和应用程序打印“Spyder服务已停止”并退出,但我不理解两者之间的区别:`
t=Timer(10,self.handle\u exit2)
t.start()
def handle\u exit2(self):
self.daemon\u context.stop\u event.set()