我试图在python中创建zmq的高级接口 这是它的样子
from abc import ABCMeta, abstractmethod
import zmq
from abstracts.BaseMessagingNode import BaseMessagingNode
__author__ = 'michael'
class BaseZmqNode():
__metaclass__ = ABCMeta
def __init__(self, host, port, bind, hwm):
self.node = self.create_node()
self.node.host = host
self.port = port
self.context = zmq.Context().instance()
self.socket = self.create_socket()
if bind:
self.socket.bind(self.build_address(host, port))
else:
self.socket.connect(self.build_address(host, port))
self.set_hwm(hwm)
def set_hwm(self, hwm):
self.socket.set_hwm(hwm)
def send_multipart(self, message):
self.socket.send_multipart(message)
def send_json(self, json):
self.socket.send_json(json)
def create_node(self):
return BaseMessagingNode
def close(self):
self.socket.close()
@staticmethod
def build_address(host, port):
strings = [host, ':', str(port)]
return ''.join(strings)
@abstractmethod
def create_socket(self):
pass
from abc import ABCMeta
from zeromq.ZmqLoopRunner import ZmqLoopRunner
from zmq.eventloop.zmqstream import ZMQStream
from abstracts.ReceivingNode import ReceivingNode
from zeromq.BaseZmqNode import BaseZmqNode
__author__ = 'michael'
class BaseZmqReceiver(BaseZmqNode):
__metaclass__ = ABCMeta
def __init__(self, host, port, hwm, bind, on_receive_callback):
super(BaseZmqReceiver, self).__init__(host=host, port=port, bind=bind, hwm=hwm)
self.node.on_message_callback = on_receive_callback
self.stream = ZMQStream(self.socket)
self.stream.on_recv(self.on_message_received)
self.runner = ZmqLoopRunner()
self.runner.start()
def on_message_received(self, message):
return self.node.on_message_callback(message)
def create_node(self):
return ReceivingNode(None, None)
def close(self):
# super(BaseZmqReceiver, self).close()
self.runner.stop()
self.stream.close()
# self.socket.close()
from threading import Thread
from zmq.eventloop import IOLoop
__author__ = 'michael'
class ZmqLoopRunner(Thread):
def __init__(self):
super(ZmqLoopRunner, self).__init__()
self.loop = IOLoop.current()
def run(self):
self.loop.start()
def stop(self):
self.loop.add_callback(self.loop.stop)
所以基本上我试图在单独的线程中运行ioloop,因此它不会阻止使用zmq进行通信的应用程序。
我有一套测试,全部通过我的代码。但在三分之一的运行中,我有这个例外。我甚至不知道从哪里开始......
File "/opt/leos/code/messaging_system/zeromq/ZmqLoopRunner.py", line 12, in run
self.loop.start()
File "/Library/Python/2.7/site-packages/zmq/eventloop/ioloop.py", line 160, in start
super(ZMQIOLoop, self).start()
File "/Library/Python/2.7/site-packages/tornado/ioloop.py", line 646, in start
event_pairs = self._impl.poll(poll_timeout)
File "/Library/Python/2.7/site-packages/zmq/eventloop/ioloop.py", line 132, in poll
z_events = self._poller.poll(1000*timeout)
File "/Library/Python/2.7/site-packages/zmq/sugar/poll.py", line 110, in poll
return zmq_poll(self.sockets, timeout=timeout)
File "_poll.pyx", line 125, in zmq.backend.cython._poll.zmq_poll (zmq/backend/cython/_poll.c:1705)
IndexError: list index out of range
我认为问题在于套接字和流关闭时循环没有完全关闭。
答案 0 :(得分:1)
根据docs,有两种方法可以启动IOLoop
:
make_current()
以设置正确的实例之后显式调用self.loop
IOLoop.instance()
而不是使用IOLoop.current()
来获取有效的实例。这将确保您拥有IOLoop
。注意:我没有尝试过,但怀疑这是问题所在。希望这有帮助!