python zmq 非阻塞线程接收信息
zmq 默认的接收函数是阻塞的,这会阻塞同一个进程其他操作。所以我尝试使用轮询监听避免阻塞。
import cloudpickle
import zmq
import time
# pyzmq==23.2.0
# cloudpickle==1.3.0
def send(port=5600):
context = zmq.Context()
publisher = context.socket(zmq.PUB)
publisher.bind('tcp://*:%d' % port)
while True:
time.sleep(2)
topic = 'msg'
record = {'a': 100, 'b':100}
# 传输python对象
publisher.send_serialized(
record,
serialize=lambda rec: (topic.encode(), cloudpickle.dumps(rec)),
)
class Listener:
"""
zmq非阻塞监控类
"""
def __init__(self, port=5600, topic='', timeout=0.01):
""" Constructs the Listener object with a subscriber port
over which to listen for messages
:param port: TCP port to listen on
:param topic: Topic to listen on
:param timeout: Timeout in seconds to recheck stop flag
"""
super().__init__()
self.port = port
self.topic = topic
self.context = zmq.Context()
self.subscriber = self.context.socket(zmq.SUB)
self.subscriber.setsockopt(zmq.SUBSCRIBE, topic.encode())
self.subscriber.connect('tcp://localhost:%d' % port)
# 初始化Poller
self.poller = zmq.Poller()
self.poller.register(self.subscriber, zmq.POLLIN) # 设置为POLLIN则刷新recv
self.timeout = timeout
def receive(self, flags=0):
topic, record = self.subscriber.recv_serialized(
deserialize=lambda msg: (msg[0].decode(), cloudpickle.loads(msg[1])),
flags=flags
)
return topic, record
def message_waiting(self):
"""Check if we have a message, wait at most until timeout.
轮询消息监听,间隔时间self.timeout * 1000,当监听到消息返回一个接收列表
其他:poller.poll()阻塞,直到有任何套接字上的数据。
"""
return self.poller.poll(int(self.timeout * 1000)) # poll timeout is in ms
# 监听对象
dataPoller = Listener(5600)
def Listener_func():
while True:
print("监听zmq")
# 隔0.5 秒确认一次是否接收到信息
time.sleep(0.5)
# dataPoller.message_waiting() 接收例子[(<zmq.Socket(zmq.SUB) at 0x1ecef4489e8>, 1)]
if len(dataPoller.message_waiting()) > 0:
print("监听到消息")
# 接收信息, 如果接收的是连续数据,也可以再加一个循环判断
a, b = dataPoller.receive()
broadcasted_data = {'topic': a, 'record': b}
print(broadcasted_data)
if __name__ == '__main__':
import threading
port = 5600
t1 = threading.Thread(target=send, args=(port,))
t2 = threading.Thread(target=Listener_func)
t1.start()
t2.start()
参考
zeroMQ中,zmq.Poller() ,in python 中的用法_没有水杯和雨伞的工科男的博客-CSDN博客_zmq.poller
python的zmq模块 - 简书 (jianshu.com)