Python mqtt client comparison

Time:2021-4-21

With the rise of artificial intelligence and big data, python has become one of the most popular computer programming languages with its elegant language style, rich libraries and gentle entry curve. It has begun to penetrate into various fields such as the Internet of things.

Python has many excellent mqtt client libraries, with which we can develop an mqtt client application with a very small amount of code.

This paper collects three common Python mqtt client libraries, and makes a simple comparison from the perspectives of library development and use complexity, so as to facilitate readers to choose. At the same time, the article also provides a simple Python example, you can copy the sample code to the editor and run it directly (Python 3 is required) . five + , and install the corresponding dependency package).

paho-mqtt

paho-mqttIt can be said that it is a leader in Python mqtt open source client library. It is developed by the eclipse foundation. In addition to the python library, it also supports major mainstream programming languages, such as C + +, Java, JavaScript, golang, etc. At present, python version has implemented 3.1 and 3.1.1Mqtt protocol, implemented in the latest development versionMQTT 5.0

With the support of the foundation, it is updated at the rate of one version per year. The latest version of this article is 1.5.0 (released in August 2019).

On GitHub home page, it provides a quick implementation from the beginning to the detailed interpretation of each function, covering all the parts from beginners to advanced users. Even if you encounter problems beyond the scope, you can get nearly 200000 related terms by searching on Google, which is the most popular mqtt client at present.

Getting so much attention, in addition to stable code, but also its ease of use. The interface of PAHO is very simple and elegant. You only need a small amount of code to implement mqtt subscription and message publishing.

install

pip3 install paho-mqtt

perhaps

git clone https://github.com/eclipse/paho.mqtt.python
cd paho.mqtt.python
python3 setup.py install

subscriber

import paho.mqtt.client as mqtt

#The callback function of the connection
def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    client.subscribe("$SYS/#")
    
#The callback function that receives the message
def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))
    
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.emqx.io", 1883, 60)
client.loop_forever()

Publisher

import paho.mqtt.client as mqtt
import time
def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    
client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)
for i in range(3):
    client.publish('a/b', payload=i, qos=0, retain=False)
    print(f"send {i} to a/b")
    time.sleep(1)

client.loop_forever()

You can even subscribe and publish with one line of code.

import paho.mqtt.subscribe as subscribe

#When this function is called, the program will block here until a message is sent to the PAHO / test / simple topic
msg = subscribe.simple("paho/test/simple", hostname="broker.emqx.io")
print(f"{msg.topic} {msg.payload}")
import paho.mqtt.publish as publish

#Send a message
publish.single("a/b", "payload", hostname="broker.emqx.io")
#  Or send more than one message at a time
msgs = [{'topic':"a/b", 'payload':"multiple 1"}, ("a/b", "multiple 2", 0, False)]
publish.multiple(msgs, hostname="broker.emqx.io")

HBMQTT

HBMQTTBased on Python asyncio, only mqtt protocol of 3.1.1 is supported. Because of using asyncio library, developers need to use Python version above 3.4.

The speed of CPU is much faster than that of disk, network and other IO operations. In a thread, no matter how fast the CPU executes, when it encounters IO operations, it has to stop and wait for the completion of reading and writing, which undoubtedly wastes a lot of time.

To solve this problem, python adds the feature of asynchronous io. In Python 3 . In Python 3.4, asyncio was formally included in the standard library . 5, added async / Await keyword. Users can easily use the async keyword before the function to make the function asynchronous.

Hbmqtt is based on the asyncio standard library. It allows users to set asynchronous breakpoints, through asynchronous IO, when mqtt clients receive messages or send messages, mount the current task and continue to process the next one.

But hbmqtt is much less well known. On Google, there are only more than 6000 entries about hbmqtt, and only 10 questions on stack overflow. This means that if you choose hbmqtt, you need a strong problem-solving ability.

Interestingly, hbmqtt itself is aMqtt server. You can use the hbmqtt command to turn it on.

$ hbmqtt
[2020-08-28 09:35:56,608] :: INFO - Exited state new
[2020-08-28 09:35:56,608] :: INFO - Entered state starting
[2020-08-28 09:35:56,609] :: INFO - Listener 'default' bind to 0.0.0.0:1883 (max_connections=-1)

install

pip3 install hbmqtt

perhaps

git clone https://github.com/beerfactory/hbmqtt
cd hbmqtt
python3 setup.py install

subscriber

import logging
import asyncio
from hbmqtt.client import MQTTClient, ClientException
from hbmqtt.mqtt.constants import QOS_1, QOS_2

async def uptime_coro():
    C = MQTTClient()
    await C.connect('mqtt://broker.emqx.io/')
    await C.subscribe([
            ('$SYS/broker/uptime', QOS_1),
            ('$SYS/broker/load/#', QOS_2),
         ])
    try:
        for i in range(1, 100):
            message = await C.deliver_message()
            packet = message.publish_packet
            print(f"{i}:  {packet.variable_header.topic_name} => {packet.payload.data}")
        await C.unsubscribe(['$SYS/broker/uptime', '$SYS/broker/load/#'])
        await C.disconnect()
    except ClientException as ce:
        logging.error("Client exception: %s" % ce)
        
if __name__ == '__main__':
    formatter = "[%(asctime)s] %(name)s {%(filename)s:%(lineno)d} %(levelname)s - %(message)s"
    logging.basicConfig(level=logging.DEBUG, format=formatter)
    asyncio.get_event_loop().run_until_complete(uptime_coro())

Publisher

import logging
import asyncio
import time
from hbmqtt.client import MQTTClient
from hbmqtt.mqtt.constants import QOS_0, QOS_1, QOS_2

async def test_coro():
    C = MQTTClient()
    await  C.connect('mqtt://broker.emqx.io/')
    tasks = [
        asyncio.ensure_future(C.publish('a/b', b'TEST MESSAGE WITH QOS_0', qos=QOS_0)),
        asyncio.ensure_future(C.publish('a/b', b'TEST MESSAGE WITH QOS_1', qos=QOS_1)),
        asyncio.ensure_future(C.publish('a/b', b'TEST MESSAGE WITH QOS_2', qos=QOS_2)),
    ]
    await asyncio.wait(tasks)
    logging.info("messages published")
    await C.disconnect()
    
if __name__ == '__main__':
    formatter = "[%(asctime)s] %(name)s {%(filename)s:%(lineno)d} %(levelname)s - %(message)s"
    logging.basicConfig(level=logging.DEBUG, format=formatter)
    asyncio.get_event_loop().run_until_complete(test_coro())

For more details, please refer to the official document:https://hbmqtt.readthedocs.io…

gmqtt

gmqttIt is an open source client library for individual developers. Mqtt 5.0 protocol is supported by default. If the connected mqtt proxy does not support 5.0 protocol, it will be degraded to 3.1 and connected again.

Compared with the former two, gmqtt is still in the primary development stage, and the version number of this article is 0.6.7. However, it is one of the early Python libraries supporting mqtt 5.0, so it is well-known on the Internet.

Again, it’s built on the asyncio library, so you need to use Python 3 . 4 or above.

install

pip3 install gmqtt

perhaps

git clone https://github.com/wialon/gmqtt
cd gmqtt
python3 setup.py install

subscriber

import asyncio
import os
import signal
import time
from gmqtt import Client as MQTTClient

STOP = asyncio.Event()

def on_connect(client, flags, rc, properties):
    print('Connected')
    
def on_message(client, topic, payload, qos, properties):
    print(f'RECV MSG: {topic} {payload}')
    
def on_subscribe(client, mid, qos, properties):
    print('SUBSCRIBED')
    
def on_disconnect(client, packet, exc=None):
    print('Disconnected')
    
def ask_exit(*args):
    STOP.set()

async def main(broker_host):
    client = MQTTClient("client-id")
    
    client.on_connect = on_connect
    client.on_message = on_message
    client.on_subscribe = on_subscribe
    client.on_disconnect = on_disconnect
    
    #Connect to mqtt proxy
    await client.connect(broker_host)
    
    #Subscribe to topics
    client.subscribe('TEST/#')
    
    #Send test data
    client.publish("TEST/A", 'AAA')
    client.publish("TEST/B", 'BBB')
    
    await STOP.wait()
    await client.disconnect()
    
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    
    loop.add_signal_handler(signal.SIGINT, ask_exit)
    loop.add_signal_handler(signal.SIGTERM, ask_exit)

    host = 'broker.emqx.io'
    loop.run_until_complete(main(host))

Publisher

import asyncio
import os
import signal
import time
from gmqtt import Client as MQTTClient

STOP = asyncio.Event()

def on_connect(client, flags, rc, properties):
    print('Connected')
    client.subscribe('TEST/#', qos=0)
    
def on_message(client, topic, payload, qos, properties):
    print(f'RECV MSG: {topic}, {payload}')
    
def on_disconnect(client, packet, exc=None):
    print('Disconnected')
    
def ask_exit(*args):
    STOP.set()
    
async def main(broker_host):
    client = MQTTClient("client-id")
    
    client.on_connect = on_connect
    client.on_message = on_message
    client.on_disconnect = on_disconnect
    
    await client.connect(broker_host)
    
    client.publish('TEST/TIME', str(time.time()), qos=1)
    
    await STOP.wait()
    await client.disconnect()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    
    loop.add_signal_handler(signal.SIGINT, ask_exit)
    loop.add_signal_handler(signal.SIGTERM, ask_exit)
    
    host = 'broker.emqx.io'  
    loop.run_until_complete(main(host))

How to choose

After introducing these three Python mqtt client libraries, let’s take a look at how to choose the right mqtt client library for ourselves. Each of the three clients has its own advantages and disadvantages

PAHO mqtt has the best documentation, easy to understand code style, and strong foundation support, but the current version of the documentation does not support mqtt 5.0.

Hbmqtt is implemented with asyncio library, which can optimize the delay caused by network I / O. However, the code style is not friendly, and mqtt 5.0 is also not supported.

Gmqtt is also implemented through asyncio library. Compared with hbmqtt, gmqtt has a friendly code style. Most importantly, it supports mqtt 5.0. However, the development process is slow and the future prospects are unclear.

Therefore, when selecting, you can refer to the following ideas:

  • If you are developing normally and want to use it in the production environment, PAHO mqtt is undoubtedly the best choice. Its stability and code readability are far better than the other two libraries. When you encounter problems, excellent documents and a large number of entries on the Internet can also help you find more solutions.
  • For readers who are proficient in using asyncio library, try hbmqtt and gmqtt.
  • If you want to learn, participate in open source projects, or use mqtt 5 . 0, you might as well try gmqtt and try to share a piece of code for it.

Copyright notice: This isEMQOriginal, reprint please indicate the source.

Link to the original text:https://www.emqx.io/cn/blog/comparision-of-python-mqtt-client

Recommended Today

Analysis of super comprehensive MySQL statement locking (Part 1)

A series of articles: Analysis of super comprehensive MySQL statement locking (Part 1) Analysis of super comprehensive MySQL statement locking (Part 2) Analysis of super comprehensive MySQL statement locking (Part 2) Preparation in advance Build a system to store heroes of the Three KingdomsheroTable: CREATE TABLE hero ( number INT, name VARCHAR(100), country varchar(100), PRIMARY […]