如何在ZeroMQ中以正确的方式中止context.socket.recv()?

时间:2015-06-04 22:41:16

标签: python zeromq abort

我有一个小软件,我有一个单独的线程正在等待ZeroMQ消息。我正在使用ZeroMQ的PUB / SUB通信协议。

目前我通过将变量“cont_loop”设置为False来中止该线程。

但是我发现,当没有消息到达ZeroMQ订阅者时,我无法退出该线程(不删除整个程序)。

def __init__(self):
    Thread.__init__(self)
    self.cont_loop = True

def abort(self):
    self.continue_loop = False

def run(self):
    zmq_context = zmq.Context()
    zmq_socket = zmq_context.socket(zmq.SUB)
    zmq_socket.bind("tcp://*:%s" % *(5556))
    zmq_socket.setsockopt(zmq.SUBSCRIBE, "")
    while self.cont_loop:
        data = zmq_socket.recv()
        print "Message: " + data
    zmq_socket.close()
    zmq_context.term()
    print "exit"

我尝试将socket.close()context.term()移至abort-method。因此,它关闭了订阅者,但这导致整个程序死亡。

关闭上述程序的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

问:......的正确方法是什么?

答:有很多方法可以实现既定目标。让我选择一个,作为如何处理分布式进程到进程消息传递的模型示例。

首先。假设,典型的软件设计任务中有更多的优先级。一些更高,一些更低,一些甚至更低,可以推迟执行这些低优先级子任务,以便在调度程序中有更多时间执行那些无法处理等待的子任务。

这就是说,让我们查看您的代码。正在使用的 SUB .recv()侧指令会导致两件事。一个可见 - 它在具有SUB行为的ZeroMQ套接字上执行RECEIVE操作。第二个,较不明显的是,它仍然悬挂,直到它得到一些东西"兼容"当前状态为SUB - 行为(稍后将详细说明)。

这意味着它也一直 BLOCKS ,因为这样的.recv()方法调用 UNTIL 一些未知的,本地无法控制的状态/事件重合使其传递ZeroMQ消息,其内容与"兼容" 具有此(仍然阻塞)SUB行为实例的本地预设状态。

这可能需要很长时间。

这正是为什么.recv()在控制循环中被使用的原因,外部处理同时获得了机会&做你想做的事情的责任(包括与中止相关的操作以及在适当的资源和发布时公平/优雅的终止)。

接收流程变为 .recv( flags = zmq.NOBLOCK ) 而非try: except:集。这样一种方式,你的本地进程不会失去它对事件流的控制(包括NOP就是这样)。

最好的下一步?

花点时间阅读一本精彩的宝石书," Code Connected,第1卷",ZeroMQ的共同父亲Pieter HINTJENS已经发表(也作为PDF)。

他的许多想法和他与我们分享的错误确实值得你花时间。

享受ZeroMQ的力量。它非常强大而且功能强大。值得自上而下掌握。