PyZMQ - Python bindings for ZeroMQ

raw JSON →
27.1.0 verified Tue May 12 auth: no python install: verified quickstart: stale

PyZMQ is the Python binding for the ZeroMQ (ØMQ) messaging library. ZeroMQ provides a high-performance, asynchronous messaging library, and PyZMQ allows Python applications to leverage its various messaging patterns (PUB/SUB, REQ/REP, PUSH/PULL, PAIR) for building distributed systems. The library is actively maintained with frequent minor releases, currently at version 27.1.0, and ships with bundled `libzmq` for easy installation.

pip install pyzmq
error ModuleNotFoundError: No module named 'zmq'
cause The PyZMQ library, which provides the 'zmq' module, is not installed in the current Python environment.
fix
pip install pyzmq
error zmq.error.ZMQError: Address already in use
cause The requested port for binding a ZeroMQ socket is already occupied by another process or a previously unclosed socket.
fix
Ensure all previous sockets are properly closed and unbound, or choose a different available port for binding.
error zmq.error.ZMQError: Operation cannot be accomplished in current state
cause An unsupported operation was attempted on a ZeroMQ socket type (e.g., trying to send on a SUB socket or recv on a PUB socket).
fix
Verify the socket type (e.g., zmq.REQ, zmq.REP, zmq.PUB, zmq.SUB) matches the intended messaging pattern and the specific operation being performed.
error zmq.error.Again
cause A non-blocking socket operation (e.g., recv with zmq.NOBLOCK) was called when no data was immediately available, or a send buffer was full.
fix
Handle the zmq.Again exception by retrying the operation later, using socket.poll() to wait for events, or switching to blocking operations if appropriate.
gotcha The PyPI package name is `pyzmq`, but the primary Python module to import is `zmq`. Attempting `import pyzmq` will not expose the core ZeroMQ API (though `pyzmq` itself is a valid, but less common, module).
fix Always use `import zmq` to access PyZMQ's functionality.
gotcha By default, `socket.recv()` and `socket.send()` are blocking operations. If no message is available or the send buffer is full, your application can hang indefinitely.
fix Use `socket.poll()` to check for activity, or pass `zmq.NOBLOCK` flag to `send()`/`recv()`. When using `NOBLOCK`, be prepared to handle `zmq.Again` (EAGAIN) exceptions when an operation would block.
gotcha It is crucial to properly close all sockets with `socket.close()` and terminate the ZeroMQ context with `context.term()` to release system resources. Failing to do so can lead to resource leaks, hanging processes, or prevent proper application shutdown.
fix Implement proper lifecycle management, typically using `try...finally` blocks or context managers, to ensure sockets are closed and the context is terminated.
breaking The integration with `asyncio` underwent significant changes around PyZMQ version 17.x. Older patterns of integrating with asyncio might no longer work or behave differently, particularly regarding event loop management and `asyncio.set_event_loop()`.
fix For asyncio, always use the `zmq.asyncio` module and its `Context`. Refer to the official PyZMQ documentation for the correct modern `asyncio` integration patterns.
gotcha ZeroMQ messages are 'framed' by the library, but sending multiple distinct parts requires using `socket.send_multipart()` and `socket.recv_multipart()`. Concatenating strings and sending with `send_string()` will be treated as a single message part.
fix When needing to send multiple logical parts in a single ZeroMQ message, use `socket.send_multipart(list_of_bytes_or_strings)` and `socket.recv_multipart()`.
python os / libc variant status wheel install import disk
3.10 alpine (musl) pyzmq wheel - 0.05s 24.9M
3.10 alpine (musl) 'pyzmq==27.1.0' - - 0.05s 24.9M
3.10 alpine (musl) pyzmq - - 0.06s 24.9M
3.10 slim (glibc) pyzmq wheel 2.1s 0.03s 22M
3.10 slim (glibc) 'pyzmq==27.1.0' - - 0.04s 22M
3.10 slim (glibc) pyzmq - - 0.04s 22M
3.11 alpine (musl) pyzmq wheel - 0.09s 27.0M
3.11 alpine (musl) 'pyzmq==27.1.0' - - 0.11s 27.0M
3.11 alpine (musl) pyzmq - - 0.11s 27.0M
3.11 slim (glibc) pyzmq wheel 1.8s 0.08s 24M
3.11 slim (glibc) 'pyzmq==27.1.0' - - 0.08s 24M
3.11 slim (glibc) pyzmq - - 0.08s 24M
3.12 alpine (musl) pyzmq wheel - 0.09s 18.8M
3.12 alpine (musl) 'pyzmq==27.1.0' - - 0.09s 18.8M
3.12 alpine (musl) pyzmq - - 0.09s 18.8M
3.12 slim (glibc) pyzmq wheel 1.6s 0.11s 16M
3.12 slim (glibc) 'pyzmq==27.1.0' - - 0.09s 16M
3.12 slim (glibc) pyzmq - - 0.09s 16M
3.13 alpine (musl) pyzmq wheel - 0.08s 18.5M
3.13 alpine (musl) 'pyzmq==27.1.0' - - 0.09s 18.4M
3.13 alpine (musl) pyzmq - - 0.08s 18.4M
3.13 slim (glibc) pyzmq wheel 1.7s 0.08s 15M
3.13 slim (glibc) 'pyzmq==27.1.0' - - 0.09s 15M
3.13 slim (glibc) pyzmq - - 0.09s 15M
3.9 alpine (musl) pyzmq wheel - 0.05s 24.4M
3.9 alpine (musl) 'pyzmq==27.1.0' - - 0.05s 24.4M
3.9 alpine (musl) pyzmq - - 0.05s 24.4M
3.9 slim (glibc) pyzmq wheel 2.4s 0.04s 21M
3.9 slim (glibc) 'pyzmq==27.1.0' - - 0.05s 21M
3.9 slim (glibc) pyzmq - - 0.04s 21M

This quickstart demonstrates how to initialize PyZMQ, create a context and a PUSH socket, bind it to a local address, and send a simple string message. It also shows proper cleanup of sockets and context.

import zmq

# Get PyZMQ and underlying ZeroMQ library versions
print(f"PyZMQ version: {zmq.__version__}")
print(f"ZeroMQ library version: {zmq.zmq_version()}\n")

# Create a ZeroMQ context, which manages connections and sockets
context = zmq.Context()

# Create a PUSH socket (a simple one-way message sender)
socket = context.socket(zmq.PUSH)

try:
    # Bind the socket to a random ephemeral port on localhost
    # In a real application, you'd bind/connect to a known address
    port = socket.bind_to_random_port("tcp://127.0.0.1")
    print(f"PUSH socket bound to tcp://127.0.0.1:{port}")

    # Send a message
    message = "Hello from PyZMQ!"
    socket.send_string(message)
    print(f"Sent message: '{message}'")

except zmq.ZMQError as e:
    print(f"ZeroMQ Error occurred: {e}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
finally:
    # Always close sockets and terminate the context to release resources
    if socket:
        socket.close()
        print("Socket closed.")
    if context:
        context.term()
        print("Context terminated.")