aiozmq 1.0.0
ZeroMQ integration with asyncio.
License: BSD

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.