asyncio integration with ZeroMQ
===============================
asyncio (PEP 3156) support for ZeroMQ.
.. image:: https://travis-ci.com/aio-libs/aiozmq.svg?branch=master
:target: https://travis-ci.com/aio-libs/aiozmq
The difference between ``aiozmq`` and vanilla ``pyzmq`` (``zmq.asyncio``) is:
``zmq.asyncio`` works only by replacing the *base event loop* with a custom one.
This approach works but has two disadvantages:
1. ``zmq.asyncio.ZMQEventLoop`` cannot be combined with
other loop implementations (most notable is the ultra fast ``uvloop``).
2. It uses the internal ZMQ Poller which has fast ZMQ Sockets support
but isn't intended to work fast with many (thousands) regular TCP sockets.
In practice it means that ``zmq.asyncio`` is not recommended to be used with
web servers like ``aiohttp``.
See also https://github.com/zeromq/pyzmq/issues/894
Documentation
-------------
See http://aiozmq.readthedocs.org
Simple high-level client-server RPC example:
.. code-block:: python
import asyncio
import aiozmq.rpc
class ServerHandler(aiozmq.rpc.AttrHandler):
@aiozmq.rpc.method
def remote_func(self, a:int, b:int) -> int:
return a + b
async def go():
server = await aiozmq.rpc.serve_rpc(
ServerHandler(), bind='tcp://127.0.0.1:5555')
client = await aiozmq.rpc.connect_rpc(
connect='tcp://127.0.0.1:5555')
ret = await client.call.remote_func(1, 2)
assert 3 == ret
server.close()
client.close()
asyncio.run(go())
Low-level request-reply example:
.. code-block:: python
import asyncio
import aiozmq
import zmq
async def go():
router = await aiozmq.create_zmq_stream(
zmq.ROUTER,
bind='tcp://127.0.0.1:*')
addr = list(router.transport.bindings())[0]
dealer = await aiozmq.create_zmq_stream(
zmq.DEALER,
connect=addr)
for i in range(10):
msg = (b'data', b'ask', str(i).encode('utf-8'))
dealer.write(msg)
data = await router.read()
router.write(data)
answer = await dealer.read()
print(answer)
dealer.close()
router.close()
asyncio.run(go())
Comparison to pyzmq
-------------------
``zmq.asyncio`` provides an *asyncio compatible loop* implementation.
But it's based on ``zmq.Poller`` which doesn't work well with massive
non-zmq socket usage.
E.g. if you build a web server for handling at least thousands of
parallel web requests (1000-5000) ``pyzmq``'s internal poller will be slow.
``aiozmq`` works with epoll natively, it doesn't need a custom loop
implementation and cooperates pretty well with `uvloop` for example.
For details see https://github.com/zeromq/pyzmq/issues/894
Requirements
------------
* Python_ 3.6+
* pyzmq_ 13.1+
* optional submodule ``aiozmq.rpc`` requires msgpack_ 0.5+
License
-------
aiozmq is offered under the BSD license.
.. _python: https://www.python.org/
.. _pyzmq: https://pypi.python.org/pypi/pyzmq
.. _asyncio: https://pypi.python.org/pypi/asyncio
.. _msgpack: https://pypi.python.org/pypi/msgpack
CHANGES
-------
1.0.0 (2022-11-02)
^^^^^^^^^^^^^^^^^^
* Support Python 3.9, 3.10, and 3.11 (thanks in part to Esben Sonne)
* Drop support for Python 3.5
* Remove support for using annotations as conversion functions
0.9.0 (2020-01-25)
^^^^^^^^^^^^^^^^^^
* Support Python 3.7 and 3.8
0.8.0 (2016-12-07)
^^^^^^^^^^^^^^^^^^
* Respect `events_backlog` parameter in zmq stream creation #86
0.7.1 (2015-09-20)
^^^^^^^^^^^^^^^^^^
* Fix monitoring events implementation
* Make the library compatible with Python 3.5
0.7.0 (2015-07-31)
^^^^^^^^^^^^^^^^^^
* Implement monitoring ZMQ events #50
* Do deeper lookup for inhereted classes #54
* Relax endpont check #56
* Implement monitoring events for stream api #52
0.6.1 (2015-05-19)
^^^^^^^^^^^^^^^^^^
* Dynamically get list of pyzmq socket types
0.6.0 (2015-02-14)
^^^^^^^^^^^^^^^^^^
* Process asyncio specific exceptions as builtins.
* Add repr(exception) to rpc server call logs if any
* Add transport.get_write_buffer_limits() method
* Add __repr__ to transport
* Add zmq_type to tr.get_extra_info()
* Add zmq streams
0.5.2 (2014-10-09)
^^^^^^^^^^^^^^^^^^
* Poll events after sending zmq message for eventless transport
0.5.1 (2014-09-27)
^^^^^^^^^^^^^^^^^^
* Fix loopless transport implementation.
0.5.0 (2014-08-23)
^^^^^^^^^^^^^^^^^^
* Support zmq devices in aiozmq.rpc.serve_rpc()
* Add loopless 0MQ transport
0.4.1 (2014-07-03)
^^^^^^^^^^^^^^^^^^
* Add exclude_log_exceptions parameter to rpc servers.
0.4.0 (2014-05-28)
^^^^^^^^^^^^^^^^^^
* Implement pause_reading/resume_reading methods in ZmqTransport.
0.3.0 (2014-05-17)
^^^^^^^^^^^^^^^^^^
* Add limited support for Windows.
* Fix unstable test execution, change ZmqEventLoop to use global
shared zmq.Context by default.
* Process cancellation on rpc servers and clients.
0.2.0 (2014-04-18)
^^^^^^^^^^^^^^^^^^
* msg in msg_received now is a list, not tuple
* Allow to send empty msg by trsansport.write()
* Add benchmarks
* Derive ServiceClosedError from aiozmq.rpc.Error, not Exception
* Implement logging from remote calls at server side (log_exceptions parameter).
* Optimize byte counting in ZmqTransport.
0.1.3 (2014-04-10)
^^^^^^^^^^^^^^^^^^
* Function default values are not passed to an annotaion.
Add check for libzmq version (should be >= 3.0)
0.1.2 (2014-04-01)
^^^^^^^^^^^^^^^^^^
* Function default values are not passed to an annotaion.
0.1.1 (2014-03-31)
^^^^^^^^^^^^^^^^^^
* Rename plural module names to single ones.
0.1.0 (2014-03-30)
^^^^^^^^^^^^^^^^^^
* Implement ZmqEventLoop with *create_zmq_connection* method which operates
on zmq transport and protocol.
* Implement ZmqEventLoopPolicy.
* Introduce ZmqTransport and ZmqProtocol.
* Implement zmq.rpc with RPC, PUSHPULL and PUBSUB protocols.