Python zeromq -- 多个发布者对单个订阅者?
我想写一个 python
脚本(叫它 parent),它要完成以下几件事:
(1) 定义一个多维的 numpy
数组。
(2) 启动 10 个不同的 python
脚本(叫它们 children)。每个脚本都能在任何时候读取 (1) 中的 numpy
数组的内容,只要它们还在运行。
(3) 每个 child 脚本会做自己的事情(children 之间不共享任何信息)。
(4) 在任何时候,parent 脚本都能接收来自所有 children 的消息。这些消息会被 parent 解析,并导致 (1) 中的 numpy
数组发生变化。
我该如何在 Linux
环境下用 python
来实现这个呢?我想到了使用 zeroMQ
,让 parent 成为一个单一的 订阅者,而 children 都是 发布者;这样做合理吗,还是有更好的方法?
另外,我该如何让所有 children 持续 读取 parent 定义的 numpy
数组的内容呢?
3 个回答
在ZeroMQ中,每个端口只能有一个发布者。唯一的(虽然不太好)解决办法是让每个子PUB套接字在不同的端口上启动,然后让父进程监听所有这些端口。
不过,用户手册中提到的管道模式是一个更好的解决方案。
我觉得使用PUSH/PULL套接字更合适,因为你有一个标准的通风口 - 工人 - 排水口场景,只不过通风口和排水口是同一个过程。
另外,考虑使用multiprocessing模块,而不是ZeroMQ。这样可能会简单一些。
这里提到的 sub
通道不一定非得是绑定的那一方,你可以让订阅者去绑定,而每个子 pub
通道可以连接到这个订阅者,并发送它们的信息。在这种情况下,我觉得 multiprocessing
模块可能更合适,但我觉得提一下也不错:
import zmq
import threading
# So that you can copy-and-paste this into an interactive session, I'm
# using threading, but obviously that's not what you'd use
# I'm the subscriber that multiple clients are writing to
def parent():
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, 'Child:')
# Even though I'm the subscriber, I'm allowed to get this party
# started with `bind`
socket.bind('tcp://127.0.0.1:5000')
# I expect 50 messages
for i in range(50):
print 'Parent received: %s' % socket.recv()
# I'm a child publisher
def child(number):
context = zmq.Context()
socket = context.socket(zmq.PUB)
# And even though I'm the publisher, I can do the connecting rather
# than the binding
socket.connect('tcp://127.0.0.1:5000')
for data in range(5):
socket.send('Child: %i %i' % (number, data))
socket.close()
threads = [threading.Thread(target=parent)] + [threading.Thread(target=child, args=(i,)) for i in range(10)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
特别是,文档中的 核心消息模式 部分讨论了在这些模式中,任一方都可以进行绑定(而另一方则连接)。