【发布时间】:2015-08-06 16:22:32
【问题描述】:
我正在使用 PYZMQ,但似乎我无法再捕获 SIGTERM。如何优雅地处理 SIGTERM ?
下面是代码sn-p:
from time import sleep
from signal import signal, SIGTERM, SIGINT
from threading import Lock, Thread
try:
import cPickle as pickle
except ImportError:
import pickle
import zmq
zmq_poller = None
class server(Thread, object):
def __init__(self, transport):
self.context = zmq.Context()
self.zmq_socket = self.context.socket(zmq.PULL)
self.zmq_socket.setsockopt(zmq.RCVTIMEO, 2000)
self.zmq_socket.bind(transport)
self.keep_running = True
Thread.__init__(self)
def process_data(self, data):
data = self.decode(data)
def decode(self, data):
return pickle.loads(data)
def run(self):
while self.keep_running:
try:
data = self.zmq_socket.recv()
self.process_data(data)
except zmq.error.Again:
pass
except zmq.error as e:
print e
def stop(self):
self.keep_running = False
def handle_stop(signum=None, frame=None):
if zmq_poller:
zmq_poller.stop()
if __name__ == '__main__':
signal(SIGTERM, handle_stop)
signal(SIGINT, handle_stop)
mc = server('ipc:///tmp/abc')
zmq_poller = mc
mc.setDaemon(True)
mc.start()
mc.join()
sleep(100)
如我们所见,如果我向进程发送 SIGTERM, SIGINT,则不会调用 handle_stop 信号处理程序
【问题讨论】:
-
将您想要完成的事情生成到子线程中,并为您想要处理的信号创建一个信号处理程序。 Python 只能处理到父线程的信号,因此这将允许您隔离子线程的行为。如果子线程使用锁等操作系统资源,则需要小心正确地终止子线程。
-
首先这是
Thread的错误实现。我认为你不应该在父母身上睡 100 秒。您需要唤醒父线程才能处理信号。我会避免使用守护进程,因为它们会导致不良或意外的行为。我会检查线程是否应该在 run() 函数中死掉,如果有的话,我会做一个小小的睡眠。 -
我会将套接字设置为具有超时的阻塞,然后在每次超时结束时检查子线程是否应该在 run() 内终止。如果超时时间很短,您可以很好地结束程序。您将需要安排父线程以处理您的信号处理程序,因此您不能使用睡眠。你应该以某种频率在父母身上旋转。我不知道是否有可能在 join() 上捕获信号。
-
@Matt 睡眠 100 秒仅用于测试目的。在生产代码中,不会这样使用
-
由于只有父线程可以捕获信号,并且由于您的父线程没有调度,所以它无法捕获任何信号。
标签: python signals zeromq pyzmq