Package: zeroless
Yet anotherØMQwrapper for Python. However, differing fromPyZMQ, which
tries to stay very close to the C++ implementation, this project aims to
make distributed systems employingØMQas pythonic as possible.Being simpler to use, Zeroless doesn’t supports all of the fine aspects
and features ofØMQ. However, you can expect to find all the message
passing patterns you were accustomed to (i.e. pair, request/reply,
publisher/subscriber, push/pull). Depite that, the only transport
available is TCP, as threads are not as efficient in Python due to the
GIL and IPC is unix-only.Installation$pipinstallzerolessPython APIIn thezerolessmodule, two classes can be used to define how distributed
entities are related (i.e.ServerandClient). To put it bluntly, with
the exception of the pair pattern, a client may be connected to multiple
servers, while a server may accept incoming connections from multiple clients.Both servers and clients are able to create acallableand/oriterable,
depending on the message passing pattern. So that you can iterate over incoming
messages and/or call to transmit a message.All examples assume:fromzerolessimport(Server,Client)Push-PullUseful for distributing the workload among a set of workers. A common
pattern in the Stream Processing field, being the cornestone of
applications like Apache Storm for instance. Also, it can be seen as a
generalisation of the Map-Reduce pattern.# Binds the pull server to port 12345# And assigns an iterable to wait for incoming messageslisten_for_push=Server(port=12345).pull()formsginlisten_for_push:print(msg)# Connects the client to as many servers as desiredclient=Client()client.connect_local(port=12345)# Initiate a push client# And assigns a callable to push messagespush=client.push()formsgin[b"Msg1",b"Msg2",b"Msg3"]:push(msg)Publisher-SubscriberUseful for broadcasting messages to a set of peers. A common pattern for
allowing real-time notifications at the client side, without having to
resort to inneficient approaches like pooling. Online services like
PubNub or IoT protocols like MQTT are examples of this pattern usage.# Binds the publisher server to port 12345# And assigns a callable to publish messages with the topic 'sh'pub=Server(port=12345).pub(topic=b'sh',embed_topic=True)# Gives publisher some time to get initial subscriptionssleep(1)formsgin[b"Msg1",b"Msg2",b"Msg3"]:pub(msg)# Connects the client to as many servers as desiredclient=Client()client.connect_local(port=12345)# Initiate a subscriber client# Assigns an iterable to wait for incoming messages with the topic 'sh'listen_for_pub=client.sub(topics=[b'sh'])fortopic,msginlisten_for_pub:print(topic,' - ',msg)Note: ZMQ’s topic filtering capabilities are publisher side since ZMQ 3.0.Last but not least, SUB sockets that bind will not get any message before they
first ask for via the provided generator, so prefer to bind PUB sockets if
missing some messages is not an option.Request-ReplyUseful for RPC style calls. A common pattern for clients to request data
and receive a response associated with the request. The HTTP protocol is
well-known for adopting this pattern, being it essential for Restful
services.# Binds the reply server to port 12345# And assigns a callable and an iterable# To both transmit and wait for incoming messagesreply,listen_for_request=Server(port=12345).reply()formsginlisten_for_request:print(msg)reply(msg)# Connects the client to as many servers as desiredclient=Client()client.connect_local(port=12345)# Initiate a request client# And assigns a callable and an iterable# To both transmit and wait for incoming messagesrequest,listen_for_reply=client.request()formsgin[b"Msg1",b"Msg2",b"Msg3"]:request(msg)response=next(listen_for_reply)print(response)PairMore often than not, this pattern will be unnecessary, as the above ones
or the mix of them suffices most use cases in distributed computing.
Regarding its capabilities, this pattern is the most similar alternative
to usual posix sockets among the aforementioned patterns. Therefore,
expect one-to-one and bidirectional communication.# Binds the pair server to port 12345# And assigns a callable and an iterable# To both transmit and wait for incoming messagespair,listen_for_pair=Server(port=12345).pair()formsginlisten_for_pair:print(msg)pair(msg)# Connects the client to a single serverclient=Client()client.connect_local(port=12345)# Initiate a pair client# And assigns a callable and an iterable# To both transmit and wait for incoming messagespair,listen_for_pair=client.pair()formsgin[b"Msg1",b"Msg2",b"Msg3"]:pair(msg)response=next(listen_for_pair)print(response)LoggingThezerolessmodule allows logging via a globalLogger object.fromzerolessimportlogTo enable it, just add anHandler objectand set an appropriatelogging level.TestingTo run individual tests:$py.testtests/test_desired_module.pyTo run all the tests:$pythonsetup.pytestAlternatively, you can use tox:$toxNeed help?For more information, please see ourdocumentation.LicenseCopyright 2014 Lucas Lira Gomesx8lucas8x@gmail.comThis library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
General Public License for more details.You should have received a copy of the GNU Lesser General Public License
along with this library. If not, seehttp://www.gnu.org/licenses/.