Living Systems_

Basic PUB/SUB connection with ZeroMQ in Python

ZeroMQ is a great way to quickly and simply send messages between multiple programs running on the same or different computers. It is very simple and robust since it doesn’t need any central server. Instead it talks directly between the programs through sockets, TCP-connections or similar.

ZeroMQ has client libraries for basically all commonly used programming languages, but when testing out that a connection works between e.g. two different machines, it might be good to keep things simple and test just the connection, as simply as possible. For this purpose, I have came to use the following two python scripts, where one sets up a “publisher”, and the other a “subscriber” process. I’m documenting them here since I tend to forget the syntax from time to time, and also some details, such as that you have to make sure the subscriber subscribes to one or all topics.

First, to install ZeroMQ in python, use conda install pyzmq or pip install pyzmq depending on which python package manager you use.

The publisher (pub.py)

import zmq
import time

ctx = zmq.Context()
sock = ctx.socket(zmq.PUB)
sock.bind("tcp://*:1234")

print("Starting loop...")
i = 1
while True:
    msg = "Hi for the %d:th time..." % i
    sock.send_string(msg)
    print("Sent string: %s ..." % msg)
    i += 1
    time.sleep(1)

sock.close()
ctx.term()

The subscriber (sub.py)

import zmq
import time

ctx = zmq.Context()
sock = ctx.socket(zmq.SUB)
sock.connect("tcp://127.0.0.1:1234")
sock.subscribe("") # Subscribe to all topics

print("Starting receiver loop ...")
while True:
    msg = sock.recv_string()
    print("Received string: %s ..." % msg)

sock.close()
ctx.term()

Then, if you run these on the same machines, you can leave the IP-addresses as is. On the other hand, if you put these on different machines, you will need to change the IP address given to sock.connect() in the subscriber script to the IP-address of the machine where the publisher script is located.

Then you just run these two scripts in a terminal and hope to see the same string that the publisher sends, being output on the subscriber side too.

If you run this in MSYS2 on Windows (as I have blogged about before ), note that you need to run python through winpty:

$ winpty python pub.py
Starting loop...
Sent string: Hi for the 1:th time... ...
Sent string: Hi for the 2:th time... ...
Sent string: Hi for the 3:th time... ...
Sent string: Hi for the 4:th time... ...
Sent string: Hi for the 5:th time... ...
Sent string: Hi for the 6:th time... ...
Sent string: Hi for the 7:th time... ...

… and:

$ winpty python sub.py
Starting receiver loop ...
Received string: Hi for the 2:th time... ...
Received string: Hi for the 3:th time... ...
Received string: Hi for the 4:th time... ...
Received string: Hi for the 5:th time... ...
Received string: Hi for the 6:th time... ...
Received string: Hi for the 7:th time... ...

Updates 2020-02-11: Fixed broken code example (some lines had ended up in the wrong code example).