Python binding for omq.rs (Rust libzmq port). Drop-in pyzmq replacement on the common path.
Project description
pyomq
Python binding for omq.rs, a Rust libzmq port. Drop-in pyzmq replacement on the common path.
Install
uv pip install pyomq
uv pip install 'pyomq[test]' # adds pytest, pyzmq for the interop suite
The published wheel includes optional features: plain, curve, lz4, zstd.
Use pyomq.has("curve") at runtime to check availability.
Usage
import pyomq as zmq # drop-in for `import zmq` from pyzmq
ctx = zmq.Context()
push = ctx.socket(zmq.PUSH)
push.connect("tcp://127.0.0.1:5555")
push.send(b"hello")
push.close()
ctx.term()
For asynchronous code:
import pyomq
import pyomq.asyncio as zmq_async
ctx = zmq_async.Context()
sock = ctx.socket(pyomq.PUSH)
await sock.connect("tcp://127.0.0.1:5555")
await sock.send(b"hello")
await sock.close()
Status
Sync and asyncio APIs both ship in this release. All 19 ZMTP socket types are wired:
- Standard (RFC 28 + 47): PAIR, PUB, SUB, REQ, REP, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB.
- Draft: SERVER, CLIENT (RFC 41), RADIO, DISH (RFC 48), GATHER, SCATTER (RFC 49), PEER, CHANNEL (RFC 51).
Transports: tcp://, ipc://, inproc://, and udp:// (RADIO/DISH only).
Optional features built into the wheel: plain, curve, lz4, zstd.
DISH groups: use socket.join(b"group") / socket.leave(b"group") to manage
subscriptions; messages are sent as multipart [group, body].
Backend
pyomq is built on omq-compio (single-threaded io_uring on Linux). The runtime
runs on a dedicated background thread; every Python call releases the GIL
across the runtime trip. This is the only backend pyomq supports — the
omq-tokio backend exists in the upstream Rust workspace for callers that need
a multi-thread tokio integration, but pyomq's per-call overhead is shaped
around compio's single-thread invariant.
Performance
See BENCHMARKS.md for full tables.
Loopback PUSH/PULL throughput vs pyzmq, on a Linux 6.12 (Debian 13) VM on an Intel Mac Mini 2018 (i7-8700B, 3.2 GHz), Rust 1.95.0, default features:
| Size | inproc pyomq | inproc pyzmq | ratio | tcp pyomq | tcp pyzmq | ratio |
|---|---|---|---|---|---|---|
| 128 B | 1.59 M/s | 497 k/s | 3.21× | 1.53 M/s | 472 k/s | 3.25× |
| 512 B | 1.56 M/s | 502 k/s | 3.11× | 1.40 M/s | 458 k/s | 3.06× |
| 2 KiB | 1.48 M/s | 450 k/s | 3.28× | 1.02 M/s | 361 k/s | 2.84× |
| 8 KiB | 1.32 M/s | 364 k/s | 3.62× | 334 k/s | 109 k/s | 3.06× |
| 32 KiB | 738 k/s | 185 k/s | 3.98× | 110 k/s | 46 k/s | 2.42× |
REQ/REP latency (TCP loopback)
Serial ping-pong: 1000 warmup + 10000 measured iterations per cell. Lower is better; ratio = pyzmq / pyomq.
| Size | pyomq p50 | pyzmq p50 | ratio | pyomq p99 | pyzmq p99 | ratio |
|---|---|---|---|---|---|---|
| 128 B | 64.4 µs | 72.8 µs | 1.13× | 80.9 µs | 88.9 µs | 1.10× |
| 512 B | 62.9 µs | 70.0 µs | 1.11× | 80.2 µs | 95.5 µs | 1.19× |
| 2 KiB | 63.8 µs | 71.5 µs | 1.12× | 87.7 µs | 96.7 µs | 1.10× |
| 8 KiB | 69.6 µs | 89.6 µs | 1.29× | 97.9 µs | 122 µs | 1.25× |
| 32 KiB | 84.9 µs | 102 µs | 1.20× | 110 µs | 118 µs | 1.07× |
zmq.proxy() forwarding (128 B, TCP)
| pyomq | pyzmq | ratio | |
|---|---|---|---|
| PUSH/PULL msg/s | 1.13 M/s | 545 k/s | 2.08× |
| REQ/REP rt/s | 11,022/s | 6,497/s | 1.70× |
pyomq's proxy() forwards directly between sockets on the compio thread —
no rings, no Python per-message overhead. pyzmq's zmq.proxy() calls libzmq's
C-level zmq_proxy. PUSH/PULL forwarding is throughput-bound and pyomq is ~2.5×
faster. REQ/REP proxy is latency-bound (4 TCP hops per round-trip); pyomq is
~1.7× faster thanks to direct socket forwarding.
Run scripts/update_perf.py (after maturin develop --release) to re-measure and update the tables above.
Compression transports
OMQ.rs adds two transparent compression transports on top of TCP: lz4+tcp://
(fast, low-latency) and zstd+tcp:// (higher ratio, better for large or
structured payloads). Swap the scheme in your endpoint string and everything
else stays the same:
push = ctx.socket(zmq.PUSH)
push.bind("lz4+tcp://127.0.0.1:5555") # or zstd+tcp://
pull = ctx.socket(zmq.PULL)
pull.connect("lz4+tcp://127.0.0.1:5555")
Both peers must use a matching compression endpoint. Payloads below ~512 B are sent as-is (the codec detects that compression would expand them). For realistic JSON payloads at 2 KiB, lz4 yields ~3.8× and zstd ~4.5× on a bandwidth-limited link.
zstd+tcp:// also auto-trains a dictionary: it samples the first 1000
outbound messages (or 100 KiB of plaintext, whichever comes first), builds an
8 KiB dict, and ships it to the peer once. After that the compression threshold
drops from 512 B to 64 B, so small structured messages start compressing too.
lz4+tcp:// does not auto-train (LZ4 has no standard dict trainer).
Virtual throughput on bandwidth-limited links (JSON payloads, compio backend):
See BENCHMARKS_COMPRESSION.md for full tables including dict-trained ratios.
CURVE authentication
CURVE encrypts traffic and authenticates the server to the client. To also
authenticate clients to the server, call set_curve_auth() before
bind()/connect():
server_pub, server_sec = zmq.curve_keypair()
client_pub, client_sec = zmq.curve_keypair()
pull = ctx.socket(zmq.PULL)
pull.curve_server = 1
pull.curve_publickey = server_pub
pull.curve_secretkey = server_sec
# Option 1: allow specific client keys (checked in Rust, no GIL overhead)
pull.set_curve_auth([client_pub])
# Option 2: custom callback receiving a PeerInfo with a .public_key (Z85 bytes)
pull.set_curve_auth(lambda peer: peer.public_key in allowed_keys)
# Option 3: accept any valid CURVE client (the default)
pull.set_curve_auth(None)
No ZAP, no filesystem key management. The callback runs during the CURVE handshake; returning a falsy value rejects the client.
BLAKE3ZMQ authentication
BLAKE3ZMQ is an omq-native encryption mechanism using BLAKE3 key derivation and ChaCha20 encryption. Keys are raw 32-byte X25519 keypairs (not Z85-encoded like CURVE). Setup mirrors CURVE:
server_pub, server_sec = zmq.blake3zmq_keypair()
client_pub, client_sec = zmq.blake3zmq_keypair()
pull = ctx.socket(zmq.PULL)
pull.blake3zmq_server = 1
pull.blake3zmq_publickey = server_pub
pull.blake3zmq_secretkey = server_sec
push = ctx.socket(zmq.PUSH)
push.blake3zmq_serverkey = server_pub
push.blake3zmq_publickey = client_pub
push.blake3zmq_secretkey = client_sec
# Client authentication (same three options as CURVE)
pull.set_blake3zmq_auth([client_pub]) # allow list
pull.set_blake3zmq_auth(lambda peer: peer.public_key in ok) # callback
pull.set_blake3zmq_auth(None) # accept all
The callback receives a PeerInfo with a .public_key attribute (raw
32-byte bytes). Requires the blake3zmq feature (pyomq.has("blake3zmq")).
[!WARNING] BLAKE3ZMQ has not been independently security audited. It's an omq-native construction (Noise XX + BLAKE3 + X25519 + ChaCha20-BLAKE3) and should not be relied on for anything that matters until it has had third-party review. Use CURVE (RFC 26) for production / regulated workloads.
Develop
cd bindings/pyomq
uv venv && source .venv/bin/activate
uv pip install maturin pytest pyzmq
maturin develop --release
pytest -v
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyomq-0.9.0.tar.gz.
File metadata
- Download URL: pyomq-0.9.0.tar.gz
- Upload date:
- Size: 389.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f470718eb5b91c1fe3ecac42b8b9d4324ff394eb3d0482a6c90a75002b63e6a4
|
|
| MD5 |
650197af9b05ff22f314484496a2e27c
|
|
| BLAKE2b-256 |
bfed91374ce3871e70adbf023675ef895ccbf90a68e1b9182d54fbadada90960
|
Provenance
The following attestation bundles were made for pyomq-0.9.0.tar.gz:
Publisher:
release-pyomq.yml on paddor/omq.rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyomq-0.9.0.tar.gz -
Subject digest:
f470718eb5b91c1fe3ecac42b8b9d4324ff394eb3d0482a6c90a75002b63e6a4 - Sigstore transparency entry: 1611669450
- Sigstore integration time:
-
Permalink:
paddor/omq.rs@4caf718e2bef6399c807b9020dc4954253e21d00 -
Branch / Tag:
refs/tags/pyomq-v0.9.0 - Owner: https://github.com/paddor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pyomq.yml@4caf718e2bef6399c807b9020dc4954253e21d00 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyomq-0.9.0-cp39-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: pyomq-0.9.0-cp39-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.9+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8794fb3fa9cbd413d4b2c5b7c7829ed6e68c3b52c021acc6c8da06b3ba6f0b5b
|
|
| MD5 |
8c6d0a8ac5eb321f1b5169abdc16de00
|
|
| BLAKE2b-256 |
3be7d92949602732a7c4fa21291b3630dce55014eb37b3d2e503cb4794c0e21f
|
Provenance
The following attestation bundles were made for pyomq-0.9.0-cp39-abi3-musllinux_1_2_x86_64.whl:
Publisher:
release-pyomq.yml on paddor/omq.rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyomq-0.9.0-cp39-abi3-musllinux_1_2_x86_64.whl -
Subject digest:
8794fb3fa9cbd413d4b2c5b7c7829ed6e68c3b52c021acc6c8da06b3ba6f0b5b - Sigstore transparency entry: 1611670036
- Sigstore integration time:
-
Permalink:
paddor/omq.rs@4caf718e2bef6399c807b9020dc4954253e21d00 -
Branch / Tag:
refs/tags/pyomq-v0.9.0 - Owner: https://github.com/paddor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pyomq.yml@4caf718e2bef6399c807b9020dc4954253e21d00 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyomq-0.9.0-cp39-abi3-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: pyomq-0.9.0-cp39-abi3-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 1.8 MB
- Tags: CPython 3.9+, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb7c461dbddee48297060f497fc3fab84fed344c3914faef9cd2bfeb99af7f39
|
|
| MD5 |
dad7384315f34dcc2e52caa06df6903e
|
|
| BLAKE2b-256 |
d70ea44aebcb178e2d4b8ef2cca8f74694b5d2f76a82291128580f154ce5548e
|
Provenance
The following attestation bundles were made for pyomq-0.9.0-cp39-abi3-musllinux_1_2_aarch64.whl:
Publisher:
release-pyomq.yml on paddor/omq.rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyomq-0.9.0-cp39-abi3-musllinux_1_2_aarch64.whl -
Subject digest:
fb7c461dbddee48297060f497fc3fab84fed344c3914faef9cd2bfeb99af7f39 - Sigstore transparency entry: 1611670199
- Sigstore integration time:
-
Permalink:
paddor/omq.rs@4caf718e2bef6399c807b9020dc4954253e21d00 -
Branch / Tag:
refs/tags/pyomq-v0.9.0 - Owner: https://github.com/paddor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pyomq.yml@4caf718e2bef6399c807b9020dc4954253e21d00 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyomq-0.9.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyomq-0.9.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8db0ab406a9c568e4a12b37e0e3eee6cfb037c606cc78432d590e8669d1623b
|
|
| MD5 |
fd2ad22c78a63dfb2210e70256797f87
|
|
| BLAKE2b-256 |
e7297dc9f5cf0d9f5ba661f5e19ea155b22d71595de9c745ade838b697e9da93
|
Provenance
The following attestation bundles were made for pyomq-0.9.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release-pyomq.yml on paddor/omq.rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyomq-0.9.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
e8db0ab406a9c568e4a12b37e0e3eee6cfb037c606cc78432d590e8669d1623b - Sigstore transparency entry: 1611669836
- Sigstore integration time:
-
Permalink:
paddor/omq.rs@4caf718e2bef6399c807b9020dc4954253e21d00 -
Branch / Tag:
refs/tags/pyomq-v0.9.0 - Owner: https://github.com/paddor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pyomq.yml@4caf718e2bef6399c807b9020dc4954253e21d00 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyomq-0.9.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyomq-0.9.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef662be544d10e9c9fa5436f5ecbda43ed04b17095dc61b951e01e8bf90b0930
|
|
| MD5 |
63b16b2b053fb8b78e7be9c1f04d2718
|
|
| BLAKE2b-256 |
c17d660ec0373393b18a91d093ff6aaeaa89e1db1646dec0c1119a19cf8592f4
|
Provenance
The following attestation bundles were made for pyomq-0.9.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release-pyomq.yml on paddor/omq.rs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyomq-0.9.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
ef662be544d10e9c9fa5436f5ecbda43ed04b17095dc61b951e01e8bf90b0930 - Sigstore transparency entry: 1611669638
- Sigstore integration time:
-
Permalink:
paddor/omq.rs@4caf718e2bef6399c807b9020dc4954253e21d00 -
Branch / Tag:
refs/tags/pyomq-v0.9.0 - Owner: https://github.com/paddor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pyomq.yml@4caf718e2bef6399c807b9020dc4954253e21d00 -
Trigger Event:
push
-
Statement type: